xref: /titanic_51/usr/src/common/ficl/loader.c (revision 2e5624d5c02b1efdbaa882c16d549c1d25ae345b)
1a1bf3f78SToomas Soome /*
2a1bf3f78SToomas Soome  * Copyright (c) 2000 Daniel Capo Sobral
3a1bf3f78SToomas Soome  * All rights reserved.
4a1bf3f78SToomas Soome  *
5a1bf3f78SToomas Soome  * Redistribution and use in source and binary forms, with or without
6a1bf3f78SToomas Soome  * modification, are permitted provided that the following conditions
7a1bf3f78SToomas Soome  * are met:
8a1bf3f78SToomas Soome  * 1. Redistributions of source code must retain the above copyright
9a1bf3f78SToomas Soome  *    notice, this list of conditions and the following disclaimer.
10a1bf3f78SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
11a1bf3f78SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
12a1bf3f78SToomas Soome  *    documentation and/or other materials provided with the distribution.
13a1bf3f78SToomas Soome  *
14a1bf3f78SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15a1bf3f78SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16a1bf3f78SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17a1bf3f78SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18a1bf3f78SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19a1bf3f78SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20a1bf3f78SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21a1bf3f78SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22a1bf3f78SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23a1bf3f78SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24a1bf3f78SToomas Soome  * SUCH DAMAGE.
25a1bf3f78SToomas Soome  *
26a1bf3f78SToomas Soome  *	$FreeBSD$
27a1bf3f78SToomas Soome  */
28a1bf3f78SToomas Soome 
29a1bf3f78SToomas Soome /*
30a1bf3f78SToomas Soome  * l o a d e r . c
31a1bf3f78SToomas Soome  * Additional FICL words designed for FreeBSD's loader
32a1bf3f78SToomas Soome  */
33a1bf3f78SToomas Soome 
34*e09118e4SToomas Soome #ifndef _STANDALONE
35a1bf3f78SToomas Soome #include <sys/types.h>
36a1bf3f78SToomas Soome #include <sys/stat.h>
37a1bf3f78SToomas Soome #include <dirent.h>
38a1bf3f78SToomas Soome #include <fcntl.h>
39a1bf3f78SToomas Soome #include <stdio.h>
40a1bf3f78SToomas Soome #include <stdlib.h>
41a1bf3f78SToomas Soome #include <unistd.h>
42a1bf3f78SToomas Soome #include <strings.h>
43a1bf3f78SToomas Soome #include <termios.h>
44a1bf3f78SToomas Soome #else
45a1bf3f78SToomas Soome #include <stand.h>
46a1bf3f78SToomas Soome #include "bootstrap.h"
47a1bf3f78SToomas Soome #endif
48*e09118e4SToomas Soome #ifdef _STANDALONE
49065446baSToomas Soome #include <uuid.h>
50065446baSToomas Soome #else
51065446baSToomas Soome #include <uuid/uuid.h>
52065446baSToomas Soome #endif
53a1bf3f78SToomas Soome #include <string.h>
54a1bf3f78SToomas Soome #include "ficl.h"
55a1bf3f78SToomas Soome 
56a1bf3f78SToomas Soome /*
57a1bf3f78SToomas Soome  *		FreeBSD's loader interaction words and extras
58a1bf3f78SToomas Soome  *
59a1bf3f78SToomas Soome  *		setenv      ( value n name n' -- )
60a1bf3f78SToomas Soome  *		setenv?     ( value n name n' flag -- )
61a1bf3f78SToomas Soome  *		getenv      ( addr n -- addr' n' | -1 )
62a1bf3f78SToomas Soome  *		unsetenv    ( addr n -- )
63a1bf3f78SToomas Soome  *		copyin      ( addr addr' len -- )
64a1bf3f78SToomas Soome  *		copyout     ( addr addr' len -- )
65a1bf3f78SToomas Soome  *		findfile    ( name len type len' -- addr )
66a1bf3f78SToomas Soome  *		ccall       ( [[...[p10] p9] ... p1] n addr -- result )
67065446baSToomas Soome  *		uuid-from-string ( addr n -- addr' )
68065446baSToomas Soome  *		uuid-to-string ( addr' -- addr n | -1 )
69a1bf3f78SToomas Soome  *		.#	    ( value -- )
70a1bf3f78SToomas Soome  */
71a1bf3f78SToomas Soome 
72a1bf3f78SToomas Soome void
73a1bf3f78SToomas Soome ficlSetenv(ficlVm *pVM)
74a1bf3f78SToomas Soome {
75a1bf3f78SToomas Soome 	char *name, *value;
76a1bf3f78SToomas Soome 	char *namep, *valuep;
77a1bf3f78SToomas Soome 	int names, values;
78a1bf3f78SToomas Soome 
79a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 4, 0);
80a1bf3f78SToomas Soome 
81a1bf3f78SToomas Soome 	names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
82a1bf3f78SToomas Soome 	namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
83a1bf3f78SToomas Soome 	values = ficlStackPopInteger(ficlVmGetDataStack(pVM));
84a1bf3f78SToomas Soome 	valuep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
85a1bf3f78SToomas Soome 
86a1bf3f78SToomas Soome 	name = (char *)ficlMalloc(names+1);
87a1bf3f78SToomas Soome 	if (!name)
88a1bf3f78SToomas Soome 		ficlVmThrowError(pVM, "Error: out of memory");
89a1bf3f78SToomas Soome 	strncpy(name, namep, names);
90a1bf3f78SToomas Soome 	name[names] = '\0';
91a1bf3f78SToomas Soome 	value = (char *)ficlMalloc(values+1);
92a1bf3f78SToomas Soome 	if (!value)
93a1bf3f78SToomas Soome 		ficlVmThrowError(pVM, "Error: out of memory");
94a1bf3f78SToomas Soome 	strncpy(value, valuep, values);
95a1bf3f78SToomas Soome 	value[values] = '\0';
96a1bf3f78SToomas Soome 
97a1bf3f78SToomas Soome 	setenv(name, value, 1);
98a1bf3f78SToomas Soome 	ficlFree(name);
99a1bf3f78SToomas Soome 	ficlFree(value);
100a1bf3f78SToomas Soome }
101a1bf3f78SToomas Soome 
102a1bf3f78SToomas Soome void
103a1bf3f78SToomas Soome ficlSetenvq(ficlVm *pVM)
104a1bf3f78SToomas Soome {
105a1bf3f78SToomas Soome 	char *name, *value;
106a1bf3f78SToomas Soome 	char *namep, *valuep;
107a1bf3f78SToomas Soome 	int names, values, overwrite;
108a1bf3f78SToomas Soome 
109a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 5, 0);
110a1bf3f78SToomas Soome 
111a1bf3f78SToomas Soome 	overwrite = ficlStackPopInteger(ficlVmGetDataStack(pVM));
112a1bf3f78SToomas Soome 	names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
113a1bf3f78SToomas Soome 	namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
114a1bf3f78SToomas Soome 	values = ficlStackPopInteger(ficlVmGetDataStack(pVM));
115a1bf3f78SToomas Soome 	valuep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
116a1bf3f78SToomas Soome 
117a1bf3f78SToomas Soome 	name = (char *)ficlMalloc(names+1);
118a1bf3f78SToomas Soome 	if (!name)
119a1bf3f78SToomas Soome 		ficlVmThrowError(pVM, "Error: out of memory");
120a1bf3f78SToomas Soome 	strncpy(name, namep, names);
121a1bf3f78SToomas Soome 	name[names] = '\0';
122a1bf3f78SToomas Soome 	value = (char *)ficlMalloc(values+1);
123a1bf3f78SToomas Soome 	if (!value)
124a1bf3f78SToomas Soome 		ficlVmThrowError(pVM, "Error: out of memory");
125a1bf3f78SToomas Soome 	strncpy(value, valuep, values);
126a1bf3f78SToomas Soome 	value[values] = '\0';
127a1bf3f78SToomas Soome 
128a1bf3f78SToomas Soome 	setenv(name, value, overwrite);
129a1bf3f78SToomas Soome 	ficlFree(name);
130a1bf3f78SToomas Soome 	ficlFree(value);
131a1bf3f78SToomas Soome }
132a1bf3f78SToomas Soome 
133a1bf3f78SToomas Soome void
134a1bf3f78SToomas Soome ficlGetenv(ficlVm *pVM)
135a1bf3f78SToomas Soome {
136a1bf3f78SToomas Soome 	char *name, *value;
137a1bf3f78SToomas Soome 	char *namep;
138a1bf3f78SToomas Soome 	int names;
139a1bf3f78SToomas Soome 
140a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 2);
141a1bf3f78SToomas Soome 
142a1bf3f78SToomas Soome 	names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
143a1bf3f78SToomas Soome 	namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
144a1bf3f78SToomas Soome 
145a1bf3f78SToomas Soome 	name = (char *)ficlMalloc(names+1);
146a1bf3f78SToomas Soome 	if (!name)
147a1bf3f78SToomas Soome 		ficlVmThrowError(pVM, "Error: out of memory");
148a1bf3f78SToomas Soome 	strncpy(name, namep, names);
149a1bf3f78SToomas Soome 	name[names] = '\0';
150a1bf3f78SToomas Soome 
151a1bf3f78SToomas Soome 	value = getenv(name);
152a1bf3f78SToomas Soome 	ficlFree(name);
153a1bf3f78SToomas Soome 
154a1bf3f78SToomas Soome 	if (value != NULL) {
155a1bf3f78SToomas Soome 		ficlStackPushPointer(ficlVmGetDataStack(pVM), value);
156a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(value));
157a1bf3f78SToomas Soome 	} else
158a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
159a1bf3f78SToomas Soome }
160a1bf3f78SToomas Soome 
161a1bf3f78SToomas Soome void
162a1bf3f78SToomas Soome ficlUnsetenv(ficlVm *pVM)
163a1bf3f78SToomas Soome {
164a1bf3f78SToomas Soome 	char *name;
165a1bf3f78SToomas Soome 	char *namep;
166a1bf3f78SToomas Soome 	int names;
167a1bf3f78SToomas Soome 
168a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
169a1bf3f78SToomas Soome 
170a1bf3f78SToomas Soome 	names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
171a1bf3f78SToomas Soome 	namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
172a1bf3f78SToomas Soome 
173a1bf3f78SToomas Soome 	name = (char *)ficlMalloc(names+1);
174a1bf3f78SToomas Soome 	if (!name)
175a1bf3f78SToomas Soome 		ficlVmThrowError(pVM, "Error: out of memory");
176a1bf3f78SToomas Soome 	strncpy(name, namep, names);
177a1bf3f78SToomas Soome 	name[names] = '\0';
178a1bf3f78SToomas Soome 
179a1bf3f78SToomas Soome 	unsetenv(name);
180a1bf3f78SToomas Soome 	ficlFree(name);
181a1bf3f78SToomas Soome }
182a1bf3f78SToomas Soome 
183a1bf3f78SToomas Soome void
184a1bf3f78SToomas Soome ficlCopyin(ficlVm *pVM)
185a1bf3f78SToomas Soome {
186*e09118e4SToomas Soome #ifdef _STANDALONE
187a1bf3f78SToomas Soome 	void*		src;
188a1bf3f78SToomas Soome 	vm_offset_t	dest;
189a1bf3f78SToomas Soome 	size_t		len;
190a1bf3f78SToomas Soome #endif
191a1bf3f78SToomas Soome 
192a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 0);
193a1bf3f78SToomas Soome 
194*e09118e4SToomas Soome #ifdef _STANDALONE
195a1bf3f78SToomas Soome 	len = ficlStackPopInteger(ficlVmGetDataStack(pVM));
196a1bf3f78SToomas Soome 	dest = ficlStackPopInteger(ficlVmGetDataStack(pVM));
197a1bf3f78SToomas Soome 	src = ficlStackPopPointer(ficlVmGetDataStack(pVM));
198a1bf3f78SToomas Soome 	archsw.arch_copyin(src, dest, len);
199a1bf3f78SToomas Soome #else
200a1bf3f78SToomas Soome 	(void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
201a1bf3f78SToomas Soome 	(void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
202a1bf3f78SToomas Soome 	(void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
203a1bf3f78SToomas Soome #endif
204a1bf3f78SToomas Soome }
205a1bf3f78SToomas Soome 
206a1bf3f78SToomas Soome void
207a1bf3f78SToomas Soome ficlCopyout(ficlVm *pVM)
208a1bf3f78SToomas Soome {
209*e09118e4SToomas Soome #ifdef _STANDALONE
210a1bf3f78SToomas Soome 	void*		dest;
211a1bf3f78SToomas Soome 	vm_offset_t	src;
212a1bf3f78SToomas Soome 	size_t		len;
213a1bf3f78SToomas Soome #endif
214a1bf3f78SToomas Soome 
215a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 0);
216a1bf3f78SToomas Soome 
217*e09118e4SToomas Soome #ifdef _STANDALONE
218a1bf3f78SToomas Soome 	len = ficlStackPopInteger(ficlVmGetDataStack(pVM));
219a1bf3f78SToomas Soome 	dest = ficlStackPopPointer(ficlVmGetDataStack(pVM));
220a1bf3f78SToomas Soome 	src = ficlStackPopInteger(ficlVmGetDataStack(pVM));
221a1bf3f78SToomas Soome 	archsw.arch_copyout(src, dest, len);
222a1bf3f78SToomas Soome #else
223a1bf3f78SToomas Soome 	(void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
224a1bf3f78SToomas Soome 	(void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
225a1bf3f78SToomas Soome 	(void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
226a1bf3f78SToomas Soome #endif
227a1bf3f78SToomas Soome }
228a1bf3f78SToomas Soome 
229a1bf3f78SToomas Soome void
230a1bf3f78SToomas Soome ficlFindfile(ficlVm *pVM)
231a1bf3f78SToomas Soome {
232*e09118e4SToomas Soome #ifdef _STANDALONE
233a1bf3f78SToomas Soome 	char	*name, *type;
234a1bf3f78SToomas Soome 	char	*namep, *typep;
235a1bf3f78SToomas Soome 	int	names, types;
236a1bf3f78SToomas Soome #endif
237a1bf3f78SToomas Soome 	struct	preloaded_file *fp;
238a1bf3f78SToomas Soome 
239a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 4, 1);
240a1bf3f78SToomas Soome 
241*e09118e4SToomas Soome #ifdef _STANDALONE
242a1bf3f78SToomas Soome 	types = ficlStackPopInteger(ficlVmGetDataStack(pVM));
243a1bf3f78SToomas Soome 	typep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
244a1bf3f78SToomas Soome 	names = ficlStackPopInteger(ficlVmGetDataStack(pVM));
245a1bf3f78SToomas Soome 	namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM));
246a1bf3f78SToomas Soome 
247a1bf3f78SToomas Soome 	name = (char *)ficlMalloc(names+1);
248a1bf3f78SToomas Soome 	if (!name)
249a1bf3f78SToomas Soome 		ficlVmThrowError(pVM, "Error: out of memory");
250a1bf3f78SToomas Soome 	strncpy(name, namep, names);
251a1bf3f78SToomas Soome 	name[names] = '\0';
252a1bf3f78SToomas Soome 	type = (char *)ficlMalloc(types+1);
253a1bf3f78SToomas Soome 	if (!type)
254a1bf3f78SToomas Soome 		ficlVmThrowError(pVM, "Error: out of memory");
255a1bf3f78SToomas Soome 	strncpy(type, typep, types);
256a1bf3f78SToomas Soome 	type[types] = '\0';
257a1bf3f78SToomas Soome 
258a1bf3f78SToomas Soome 	fp = file_findfile(name, type);
259a1bf3f78SToomas Soome #else
260a1bf3f78SToomas Soome 	(void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
261a1bf3f78SToomas Soome 	(void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
262a1bf3f78SToomas Soome 	(void) ficlStackPopInteger(ficlVmGetDataStack(pVM));
263a1bf3f78SToomas Soome 	(void) ficlStackPopPointer(ficlVmGetDataStack(pVM));
264a1bf3f78SToomas Soome 
265a1bf3f78SToomas Soome 	fp = NULL;
266a1bf3f78SToomas Soome #endif
267a1bf3f78SToomas Soome 	ficlStackPushPointer(ficlVmGetDataStack(pVM), fp);
268a1bf3f78SToomas Soome }
269a1bf3f78SToomas Soome 
270a1bf3f78SToomas Soome void
271a1bf3f78SToomas Soome ficlCcall(ficlVm *pVM)
272a1bf3f78SToomas Soome {
273a1bf3f78SToomas Soome 	int (*func)(int, ...);
274a1bf3f78SToomas Soome 	int result, p[10];
275a1bf3f78SToomas Soome 	int nparam, i;
276a1bf3f78SToomas Soome 
277a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
278a1bf3f78SToomas Soome 
279a1bf3f78SToomas Soome 	func = (int (*)(int, ...))ficlStackPopPointer(ficlVmGetDataStack(pVM));
280a1bf3f78SToomas Soome 	nparam = ficlStackPopInteger(ficlVmGetDataStack(pVM));
281a1bf3f78SToomas Soome 
282a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), nparam, 1);
283a1bf3f78SToomas Soome 
284a1bf3f78SToomas Soome 	for (i = 0; i < nparam; i++)
285a1bf3f78SToomas Soome 		p[i] = ficlStackPopInteger(ficlVmGetDataStack(pVM));
286a1bf3f78SToomas Soome 
287a1bf3f78SToomas Soome 	result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
288a1bf3f78SToomas Soome 	    p[9]);
289a1bf3f78SToomas Soome 
290a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM), result);
291a1bf3f78SToomas Soome }
292a1bf3f78SToomas Soome 
293065446baSToomas Soome void
294065446baSToomas Soome ficlUuidFromString(ficlVm *pVM)
295065446baSToomas Soome {
296065446baSToomas Soome 	char	*uuid;
297065446baSToomas Soome 	char	*uuid_ptr;
298065446baSToomas Soome 	int	uuid_size;
299065446baSToomas Soome 	uuid_t	*u;
300*e09118e4SToomas Soome #ifdef _STANDALONE
301065446baSToomas Soome 	uint32_t status;
302065446baSToomas Soome #else
303065446baSToomas Soome 	int status;
304065446baSToomas Soome #endif
305065446baSToomas Soome 
306065446baSToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0);
307065446baSToomas Soome 
308065446baSToomas Soome 	uuid_size = ficlStackPopInteger(ficlVmGetDataStack(pVM));
309065446baSToomas Soome 	uuid_ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM));
310065446baSToomas Soome 
311065446baSToomas Soome 	uuid = ficlMalloc(uuid_size + 1);
312065446baSToomas Soome 	if (!uuid)
313065446baSToomas Soome 		ficlVmThrowError(pVM, "Error: out of memory");
314065446baSToomas Soome 	(void) memcpy(uuid, uuid_ptr, uuid_size);
315065446baSToomas Soome 	uuid[uuid_size] = '\0';
316065446baSToomas Soome 
317065446baSToomas Soome 	u = ficlMalloc(sizeof (*u));
318*e09118e4SToomas Soome #ifdef _STANDALONE
319065446baSToomas Soome 	uuid_from_string(uuid, u, &status);
320065446baSToomas Soome 	ficlFree(uuid);
321065446baSToomas Soome 	if (status != uuid_s_ok) {
322065446baSToomas Soome 		ficlFree(u);
323065446baSToomas Soome 		u = NULL;
324065446baSToomas Soome 	}
325065446baSToomas Soome #else
326065446baSToomas Soome 	status = uuid_parse(uuid, *u);
327065446baSToomas Soome 	ficlFree(uuid);
328065446baSToomas Soome 	if (status != 0) {
329065446baSToomas Soome 		ficlFree(u);
330065446baSToomas Soome 		u = NULL;
331065446baSToomas Soome 	}
332065446baSToomas Soome #endif
333065446baSToomas Soome 	ficlStackPushPointer(ficlVmGetDataStack(pVM), u);
334065446baSToomas Soome }
335065446baSToomas Soome 
336065446baSToomas Soome void
337065446baSToomas Soome ficlUuidToString(ficlVm *pVM)
338065446baSToomas Soome {
339065446baSToomas Soome 	char	*uuid;
340065446baSToomas Soome 	uuid_t	*u;
341*e09118e4SToomas Soome #ifdef _STANDALONE
342065446baSToomas Soome 	uint32_t status;
343065446baSToomas Soome #endif
344065446baSToomas Soome 
345065446baSToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
346065446baSToomas Soome 
347065446baSToomas Soome 	u = ficlStackPopPointer(ficlVmGetDataStack(pVM));
348*e09118e4SToomas Soome #ifdef _STANDALONE
349065446baSToomas Soome 	uuid_to_string(u, &uuid, &status);
350065446baSToomas Soome 	if (status == uuid_s_ok) {
351065446baSToomas Soome 		ficlStackPushPointer(ficlVmGetDataStack(pVM), uuid);
352065446baSToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(uuid));
353065446baSToomas Soome 	} else
354065446baSToomas Soome #else
355065446baSToomas Soome 	uuid = ficlMalloc(UUID_PRINTABLE_STRING_LENGTH);
356065446baSToomas Soome 	if (uuid != NULL) {
357065446baSToomas Soome 		uuid_unparse(*u, uuid);
358065446baSToomas Soome 		ficlStackPushPointer(ficlVmGetDataStack(pVM), uuid);
359065446baSToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(uuid));
360065446baSToomas Soome 	} else
361065446baSToomas Soome #endif
362065446baSToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
363065446baSToomas Soome }
364065446baSToomas Soome 
365a1bf3f78SToomas Soome /*
366a1bf3f78SToomas Soome  * f i c l E x e c F D
367a1bf3f78SToomas Soome  * reads in text from file fd and passes it to ficlExec()
368a1bf3f78SToomas Soome  * returns FICL_VM_STATUS_OUT_OF_TEXT on success or the ficlExec() error
369a1bf3f78SToomas Soome  * code on failure.
370a1bf3f78SToomas Soome  */
371a1bf3f78SToomas Soome #define	nLINEBUF	256
372a1bf3f78SToomas Soome int
373a1bf3f78SToomas Soome ficlExecFD(ficlVm *pVM, int fd)
374a1bf3f78SToomas Soome {
375a1bf3f78SToomas Soome 	char cp[nLINEBUF];
376a1bf3f78SToomas Soome 	int nLine = 0, rval = FICL_VM_STATUS_OUT_OF_TEXT;
377a1bf3f78SToomas Soome 	char ch;
378a1bf3f78SToomas Soome 	ficlCell id;
379a1bf3f78SToomas Soome 	ficlString s;
380a1bf3f78SToomas Soome 
381a1bf3f78SToomas Soome 	id = pVM->sourceId;
382a1bf3f78SToomas Soome 	pVM->sourceId.i = fd+1; /* in loader we can get 0, there is no stdin */
383a1bf3f78SToomas Soome 
384a1bf3f78SToomas Soome 	/* feed each line to ficlExec */
385a1bf3f78SToomas Soome 	while (1) {
386a1bf3f78SToomas Soome 		int status, i;
387a1bf3f78SToomas Soome 
388a1bf3f78SToomas Soome 		i = 0;
389a1bf3f78SToomas Soome 		while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
390a1bf3f78SToomas Soome 			cp[i++] = ch;
391a1bf3f78SToomas Soome 		nLine++;
392a1bf3f78SToomas Soome 		if (!i) {
393a1bf3f78SToomas Soome 			if (status < 1)
394a1bf3f78SToomas Soome 				break;
395a1bf3f78SToomas Soome 			continue;
396a1bf3f78SToomas Soome 		}
397a1bf3f78SToomas Soome 		if (cp[i] == '\n')
398a1bf3f78SToomas Soome 			cp[i] = '\0';
399a1bf3f78SToomas Soome 
400a1bf3f78SToomas Soome 		FICL_STRING_SET_POINTER(s, cp);
401a1bf3f78SToomas Soome 		FICL_STRING_SET_LENGTH(s, i);
402a1bf3f78SToomas Soome 
403a1bf3f78SToomas Soome 		rval = ficlVmExecuteString(pVM, s);
404a1bf3f78SToomas Soome 		if (rval != FICL_VM_STATUS_QUIT &&
405a1bf3f78SToomas Soome 		    rval != FICL_VM_STATUS_USER_EXIT &&
406a1bf3f78SToomas Soome 		    rval != FICL_VM_STATUS_OUT_OF_TEXT) {
407a1bf3f78SToomas Soome 			pVM->sourceId = id;
408a1bf3f78SToomas Soome 			(void) ficlVmEvaluate(pVM, "");
409a1bf3f78SToomas Soome 			return (rval);
410a1bf3f78SToomas Soome 		}
411a1bf3f78SToomas Soome 	}
412a1bf3f78SToomas Soome 	pVM->sourceId = id;
413a1bf3f78SToomas Soome 
414a1bf3f78SToomas Soome 	/*
415a1bf3f78SToomas Soome 	 * Pass an empty line with SOURCE-ID == -1 to flush
416a1bf3f78SToomas Soome 	 * any pending REFILLs (as required by FILE wordset)
417a1bf3f78SToomas Soome 	 */
418a1bf3f78SToomas Soome 	(void) ficlVmEvaluate(pVM, "");
419a1bf3f78SToomas Soome 
420a1bf3f78SToomas Soome 	if (rval == FICL_VM_STATUS_USER_EXIT)
421a1bf3f78SToomas Soome 		ficlVmThrow(pVM, FICL_VM_STATUS_USER_EXIT);
422a1bf3f78SToomas Soome 
423a1bf3f78SToomas Soome 	return (rval);
424a1bf3f78SToomas Soome }
425a1bf3f78SToomas Soome 
426a1bf3f78SToomas Soome static void displayCellNoPad(ficlVm *pVM)
427a1bf3f78SToomas Soome {
428a1bf3f78SToomas Soome 	ficlCell c;
429a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
430a1bf3f78SToomas Soome 
431a1bf3f78SToomas Soome 	c = ficlStackPop(ficlVmGetDataStack(pVM));
432a1bf3f78SToomas Soome 	ficlLtoa((c).i, pVM->pad, pVM->base);
433a1bf3f78SToomas Soome 	ficlVmTextOut(pVM, pVM->pad);
434a1bf3f78SToomas Soome }
435a1bf3f78SToomas Soome 
436a1bf3f78SToomas Soome /*
437a1bf3f78SToomas Soome  * isdir? - Return whether an fd corresponds to a directory.
438a1bf3f78SToomas Soome  *
439a1bf3f78SToomas Soome  * isdir? ( fd -- bool )
440a1bf3f78SToomas Soome  */
441a1bf3f78SToomas Soome static void
442a1bf3f78SToomas Soome isdirQuestion(ficlVm *pVM)
443a1bf3f78SToomas Soome {
444a1bf3f78SToomas Soome 	struct stat sb;
445a1bf3f78SToomas Soome 	ficlInteger flag;
446a1bf3f78SToomas Soome 	int fd;
447a1bf3f78SToomas Soome 
448a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 1);
449a1bf3f78SToomas Soome 
450a1bf3f78SToomas Soome 	fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
451a1bf3f78SToomas Soome 	flag = FICL_FALSE;
452a1bf3f78SToomas Soome 	do {
453a1bf3f78SToomas Soome 		if (fd < 0)
454a1bf3f78SToomas Soome 			break;
455a1bf3f78SToomas Soome 		if (fstat(fd, &sb) < 0)
456a1bf3f78SToomas Soome 			break;
457a1bf3f78SToomas Soome 		if (!S_ISDIR(sb.st_mode))
458a1bf3f78SToomas Soome 			break;
459a1bf3f78SToomas Soome 		flag = FICL_TRUE;
460a1bf3f78SToomas Soome 	} while (0);
461a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
462a1bf3f78SToomas Soome }
463a1bf3f78SToomas Soome 
464a1bf3f78SToomas Soome /*
465a1bf3f78SToomas Soome  * fopen - open a file and return new fd on stack.
466a1bf3f78SToomas Soome  *
467a1bf3f78SToomas Soome  * fopen ( ptr count mode -- fd )
468a1bf3f78SToomas Soome  */
469a1bf3f78SToomas Soome extern char *get_dev(const char *);
470a1bf3f78SToomas Soome 
471a1bf3f78SToomas Soome static void
472a1bf3f78SToomas Soome pfopen(ficlVm *pVM)
473a1bf3f78SToomas Soome {
474a1bf3f78SToomas Soome 	int mode, fd, count;
475a1bf3f78SToomas Soome 	char *ptr, *name;
476*e09118e4SToomas Soome #ifndef _STANDALONE
477a1bf3f78SToomas Soome 	char *tmp;
478a1bf3f78SToomas Soome #endif
479a1bf3f78SToomas Soome 
480a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
481a1bf3f78SToomas Soome 
482a1bf3f78SToomas Soome 	mode = ficlStackPopInteger(ficlVmGetDataStack(pVM));	/* get mode */
483a1bf3f78SToomas Soome 	count = ficlStackPopInteger(ficlVmGetDataStack(pVM));	/* get count */
484a1bf3f78SToomas Soome 	ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM));	/* get ptr */
485a1bf3f78SToomas Soome 
486a1bf3f78SToomas Soome 	if ((count < 0) || (ptr == NULL)) {
487a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
488a1bf3f78SToomas Soome 		return;
489a1bf3f78SToomas Soome 	}
490a1bf3f78SToomas Soome 
491a1bf3f78SToomas Soome 	/* ensure that the string is null terminated */
492a1bf3f78SToomas Soome 	name = (char *)malloc(count+1);
493a1bf3f78SToomas Soome 	bcopy(ptr, name, count);
494a1bf3f78SToomas Soome 	name[count] = 0;
495*e09118e4SToomas Soome #ifndef _STANDALONE
496a1bf3f78SToomas Soome 	tmp = get_dev(name);
497a1bf3f78SToomas Soome 	free(name);
498a1bf3f78SToomas Soome 	name = tmp;
499a1bf3f78SToomas Soome #endif
500a1bf3f78SToomas Soome 
501a1bf3f78SToomas Soome 	/* open the file */
502a1bf3f78SToomas Soome 	fd = open(name, mode);
503a1bf3f78SToomas Soome 	free(name);
504a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM), fd);
505a1bf3f78SToomas Soome }
506a1bf3f78SToomas Soome 
507a1bf3f78SToomas Soome /*
508a1bf3f78SToomas Soome  * fclose - close a file who's fd is on stack.
509a1bf3f78SToomas Soome  * fclose ( fd -- )
510a1bf3f78SToomas Soome  */
511a1bf3f78SToomas Soome static void
512a1bf3f78SToomas Soome pfclose(ficlVm *pVM)
513a1bf3f78SToomas Soome {
514a1bf3f78SToomas Soome 	int fd;
515a1bf3f78SToomas Soome 
516a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
517a1bf3f78SToomas Soome 
518a1bf3f78SToomas Soome 	fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
519a1bf3f78SToomas Soome 	if (fd != -1)
520a1bf3f78SToomas Soome 		close(fd);
521a1bf3f78SToomas Soome }
522a1bf3f78SToomas Soome 
523a1bf3f78SToomas Soome /*
524a1bf3f78SToomas Soome  * fread - read file contents
525a1bf3f78SToomas Soome  * fread  ( fd buf nbytes  -- nread )
526a1bf3f78SToomas Soome  */
527a1bf3f78SToomas Soome static void
528a1bf3f78SToomas Soome pfread(ficlVm *pVM)
529a1bf3f78SToomas Soome {
530a1bf3f78SToomas Soome 	int fd, len;
531a1bf3f78SToomas Soome 	char *buf;
532a1bf3f78SToomas Soome 
533a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
534a1bf3f78SToomas Soome 
535a1bf3f78SToomas Soome 	len = ficlStackPopInteger(ficlVmGetDataStack(pVM));
536a1bf3f78SToomas Soome 	buf = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get buffer */
537a1bf3f78SToomas Soome 	fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
538a1bf3f78SToomas Soome 	if (len > 0 && buf && fd != -1)
539a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM),
540a1bf3f78SToomas Soome 		    read(fd, buf, len));
541a1bf3f78SToomas Soome 	else
542a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
543a1bf3f78SToomas Soome }
544a1bf3f78SToomas Soome 
545a1bf3f78SToomas Soome /*
546a1bf3f78SToomas Soome  * fopendir - open directory
547a1bf3f78SToomas Soome  *
548a1bf3f78SToomas Soome  * fopendir ( addr len -- ptr TRUE | FALSE )
549a1bf3f78SToomas Soome  */
550a1bf3f78SToomas Soome static void pfopendir(ficlVm *pVM)
551a1bf3f78SToomas Soome {
552*e09118e4SToomas Soome #ifndef _STANDALONE
553a1bf3f78SToomas Soome 	DIR *dir;
554a1bf3f78SToomas Soome 	char *tmp;
555a1bf3f78SToomas Soome #else
556a1bf3f78SToomas Soome 	struct stat sb;
557a1bf3f78SToomas Soome 	int fd;
558a1bf3f78SToomas Soome #endif
559a1bf3f78SToomas Soome 	int count;
560a1bf3f78SToomas Soome 	char *ptr, *name;
561a1bf3f78SToomas Soome 	ficlInteger flag = FICL_FALSE;
562a1bf3f78SToomas Soome 
563a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 1);
564a1bf3f78SToomas Soome 
565a1bf3f78SToomas Soome 	count = ficlStackPopInteger(ficlVmGetDataStack(pVM));
566a1bf3f78SToomas Soome 	ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM));	/* get ptr */
567a1bf3f78SToomas Soome 
568a1bf3f78SToomas Soome 	if ((count < 0) || (ptr == NULL)) {
569a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
570a1bf3f78SToomas Soome 		return;
571a1bf3f78SToomas Soome 	}
572a1bf3f78SToomas Soome 	/* ensure that the string is null terminated */
573a1bf3f78SToomas Soome 	name = (char *)malloc(count+1);
574a1bf3f78SToomas Soome 	bcopy(ptr, name, count);
575a1bf3f78SToomas Soome 	name[count] = 0;
576*e09118e4SToomas Soome #ifndef _STANDALONE
577a1bf3f78SToomas Soome 	tmp = get_dev(name);
578a1bf3f78SToomas Soome 	free(name);
579a1bf3f78SToomas Soome 	name = tmp;
580a1bf3f78SToomas Soome #else
581a1bf3f78SToomas Soome 	fd = open(name, O_RDONLY);
582a1bf3f78SToomas Soome 	free(name);
583a1bf3f78SToomas Soome 	do {
584a1bf3f78SToomas Soome 		if (fd < 0)
585a1bf3f78SToomas Soome 			break;
586a1bf3f78SToomas Soome 		if (fstat(fd, &sb) < 0)
587a1bf3f78SToomas Soome 			break;
588a1bf3f78SToomas Soome 		if (!S_ISDIR(sb.st_mode))
589a1bf3f78SToomas Soome 			break;
590a1bf3f78SToomas Soome 		flag = FICL_TRUE;
591a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), fd);
592a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
593a1bf3f78SToomas Soome 		return;
594a1bf3f78SToomas Soome 	} while (0);
595a1bf3f78SToomas Soome 
596a1bf3f78SToomas Soome 	if (fd >= 0)
597a1bf3f78SToomas Soome 		close(fd);
598a1bf3f78SToomas Soome 
599a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
600a1bf3f78SToomas Soome 		return;
601a1bf3f78SToomas Soome #endif
602*e09118e4SToomas Soome #ifndef _STANDALONE
603a1bf3f78SToomas Soome 	dir = opendir(name);
604a1bf3f78SToomas Soome 	if (dir == NULL) {
605a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
606a1bf3f78SToomas Soome 		return;
607a1bf3f78SToomas Soome 	} else
608a1bf3f78SToomas Soome 		flag = FICL_TRUE;
609a1bf3f78SToomas Soome 
610a1bf3f78SToomas Soome 	ficlStackPushPointer(ficlVmGetDataStack(pVM), dir);
611a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM), flag);
612a1bf3f78SToomas Soome #endif
613a1bf3f78SToomas Soome }
614a1bf3f78SToomas Soome 
615a1bf3f78SToomas Soome /*
616a1bf3f78SToomas Soome  * freaddir - read directory contents
617a1bf3f78SToomas Soome  * freaddir ( fd -- ptr len TRUE | FALSE )
618a1bf3f78SToomas Soome  */
619a1bf3f78SToomas Soome static void
620a1bf3f78SToomas Soome pfreaddir(ficlVm *pVM)
621a1bf3f78SToomas Soome {
622*e09118e4SToomas Soome #ifndef _STANDALONE
623a1bf3f78SToomas Soome 	static DIR *dir = NULL;
624a1bf3f78SToomas Soome #else
625a1bf3f78SToomas Soome 	int fd;
626a1bf3f78SToomas Soome #endif
627a1bf3f78SToomas Soome 	struct dirent *d = NULL;
628a1bf3f78SToomas Soome 
629a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 3);
630a1bf3f78SToomas Soome 	/*
631a1bf3f78SToomas Soome 	 * libstand readdir does not always return . nor .. so filter
632a1bf3f78SToomas Soome 	 * them out to have consistent behaviour.
633a1bf3f78SToomas Soome 	 */
634*e09118e4SToomas Soome #ifndef _STANDALONE
635a1bf3f78SToomas Soome 	dir = ficlStackPopPointer(ficlVmGetDataStack(pVM));
636a1bf3f78SToomas Soome 	if (dir != NULL)
637a1bf3f78SToomas Soome 		do {
638a1bf3f78SToomas Soome 			d = readdir(dir);
639a1bf3f78SToomas Soome 			if (d != NULL && strcmp(d->d_name, ".") == 0)
640a1bf3f78SToomas Soome 				continue;
641a1bf3f78SToomas Soome 			if (d != NULL && strcmp(d->d_name, "..") == 0)
642a1bf3f78SToomas Soome 				continue;
643a1bf3f78SToomas Soome 			break;
644a1bf3f78SToomas Soome 		} while (d != NULL);
645a1bf3f78SToomas Soome #else
646a1bf3f78SToomas Soome 	fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
647a1bf3f78SToomas Soome 	if (fd != -1)
648a1bf3f78SToomas Soome 		do {
649a1bf3f78SToomas Soome 			d = readdirfd(fd);
650a1bf3f78SToomas Soome 			if (d != NULL && strcmp(d->d_name, ".") == 0)
651a1bf3f78SToomas Soome 				continue;
652a1bf3f78SToomas Soome 			if (d != NULL && strcmp(d->d_name, "..") == 0)
653a1bf3f78SToomas Soome 				continue;
654a1bf3f78SToomas Soome 			break;
655a1bf3f78SToomas Soome 		} while (d != NULL);
656a1bf3f78SToomas Soome #endif
657a1bf3f78SToomas Soome 	if (d != NULL) {
658a1bf3f78SToomas Soome 		ficlStackPushPointer(ficlVmGetDataStack(pVM), d->d_name);
659a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM),
660a1bf3f78SToomas Soome 		    strlen(d->d_name));
661a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), FICL_TRUE);
662a1bf3f78SToomas Soome 	} else {
663a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), FICL_FALSE);
664a1bf3f78SToomas Soome 	}
665a1bf3f78SToomas Soome }
666a1bf3f78SToomas Soome 
667a1bf3f78SToomas Soome /*
668a1bf3f78SToomas Soome  * fclosedir - close a dir on stack.
669a1bf3f78SToomas Soome  *
670a1bf3f78SToomas Soome  * fclosedir ( fd -- )
671a1bf3f78SToomas Soome  */
672a1bf3f78SToomas Soome static void
673a1bf3f78SToomas Soome pfclosedir(ficlVm *pVM)
674a1bf3f78SToomas Soome {
675*e09118e4SToomas Soome #ifndef _STANDALONE
676a1bf3f78SToomas Soome 	DIR *dir;
677a1bf3f78SToomas Soome #else
678a1bf3f78SToomas Soome 	int fd;
679a1bf3f78SToomas Soome #endif
680a1bf3f78SToomas Soome 
681a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
682a1bf3f78SToomas Soome 
683*e09118e4SToomas Soome #ifndef _STANDALONE
684a1bf3f78SToomas Soome 	dir = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get dir */
685a1bf3f78SToomas Soome 	if (dir != NULL)
686a1bf3f78SToomas Soome 		closedir(dir);
687a1bf3f78SToomas Soome #else
688a1bf3f78SToomas Soome 	fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
689a1bf3f78SToomas Soome 	if (fd != -1)
690a1bf3f78SToomas Soome 		close(fd);
691a1bf3f78SToomas Soome #endif
692a1bf3f78SToomas Soome }
693a1bf3f78SToomas Soome 
694a1bf3f78SToomas Soome /*
695a1bf3f78SToomas Soome  * fload - interpret file contents
696a1bf3f78SToomas Soome  *
697a1bf3f78SToomas Soome  * fload  ( fd -- )
698a1bf3f78SToomas Soome  */
699a1bf3f78SToomas Soome static void pfload(ficlVm *pVM)
700a1bf3f78SToomas Soome {
701a1bf3f78SToomas Soome 	int fd;
702a1bf3f78SToomas Soome 
703a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
704a1bf3f78SToomas Soome 
705a1bf3f78SToomas Soome 	fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
706a1bf3f78SToomas Soome 	if (fd != -1)
707a1bf3f78SToomas Soome 		ficlExecFD(pVM, fd);
708a1bf3f78SToomas Soome }
709a1bf3f78SToomas Soome 
710a1bf3f78SToomas Soome /*
711a1bf3f78SToomas Soome  * fwrite - write file contents
712a1bf3f78SToomas Soome  *
713a1bf3f78SToomas Soome  * fwrite  ( fd buf nbytes  -- nwritten )
714a1bf3f78SToomas Soome  */
715a1bf3f78SToomas Soome static void
716a1bf3f78SToomas Soome pfwrite(ficlVm *pVM)
717a1bf3f78SToomas Soome {
718a1bf3f78SToomas Soome 	int fd, len;
719a1bf3f78SToomas Soome 	char *buf;
720a1bf3f78SToomas Soome 
721a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
722a1bf3f78SToomas Soome 
723a1bf3f78SToomas Soome 	len = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* bytes to read */
724a1bf3f78SToomas Soome 	buf = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get buffer */
725a1bf3f78SToomas Soome 	fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */
726a1bf3f78SToomas Soome 	if (len > 0 && buf && fd != -1)
727a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM),
728a1bf3f78SToomas Soome 		    write(fd, buf, len));
729a1bf3f78SToomas Soome 	else
730a1bf3f78SToomas Soome 		ficlStackPushInteger(ficlVmGetDataStack(pVM), -1);
731a1bf3f78SToomas Soome }
732a1bf3f78SToomas Soome 
733a1bf3f78SToomas Soome /*
734a1bf3f78SToomas Soome  * fseek - seek to a new position in a file
735a1bf3f78SToomas Soome  *
736a1bf3f78SToomas Soome  * fseek  ( fd ofs whence  -- pos )
737a1bf3f78SToomas Soome  */
738a1bf3f78SToomas Soome static void
739a1bf3f78SToomas Soome pfseek(ficlVm *pVM)
740a1bf3f78SToomas Soome {
741a1bf3f78SToomas Soome 	int fd, pos, whence;
742a1bf3f78SToomas Soome 
743a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1);
744a1bf3f78SToomas Soome 
745a1bf3f78SToomas Soome 	whence = ficlStackPopInteger(ficlVmGetDataStack(pVM));
746a1bf3f78SToomas Soome 	pos = ficlStackPopInteger(ficlVmGetDataStack(pVM));
747a1bf3f78SToomas Soome 	fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
748a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM), lseek(fd, pos, whence));
749a1bf3f78SToomas Soome }
750a1bf3f78SToomas Soome 
751a1bf3f78SToomas Soome /*
752a1bf3f78SToomas Soome  * key - get a character from stdin
753a1bf3f78SToomas Soome  *
754a1bf3f78SToomas Soome  * key ( -- char )
755a1bf3f78SToomas Soome  */
756a1bf3f78SToomas Soome static void
757a1bf3f78SToomas Soome key(ficlVm *pVM)
758a1bf3f78SToomas Soome {
759a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
760a1bf3f78SToomas Soome 
761a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM), getchar());
762a1bf3f78SToomas Soome }
763a1bf3f78SToomas Soome 
764a1bf3f78SToomas Soome /*
765a1bf3f78SToomas Soome  * key? - check for a character from stdin (FACILITY)
766a1bf3f78SToomas Soome  * key? ( -- flag )
767a1bf3f78SToomas Soome  */
768a1bf3f78SToomas Soome static void
769a1bf3f78SToomas Soome keyQuestion(ficlVm *pVM)
770a1bf3f78SToomas Soome {
771*e09118e4SToomas Soome #ifndef _STANDALONE
772a1bf3f78SToomas Soome 	char ch = -1;
773a1bf3f78SToomas Soome 	struct termios oldt;
774a1bf3f78SToomas Soome 	struct termios newt;
775a1bf3f78SToomas Soome #endif
776a1bf3f78SToomas Soome 
777a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
778a1bf3f78SToomas Soome 
779*e09118e4SToomas Soome #ifndef _STANDALONE
780a1bf3f78SToomas Soome 	tcgetattr(STDIN_FILENO, &oldt);
781a1bf3f78SToomas Soome 	newt = oldt;
782a1bf3f78SToomas Soome 	newt.c_lflag &= ~(ICANON | ECHO);
783a1bf3f78SToomas Soome 	newt.c_cc[VMIN] = 0;
784a1bf3f78SToomas Soome 	newt.c_cc[VTIME] = 0;
785a1bf3f78SToomas Soome 	tcsetattr(STDIN_FILENO, TCSANOW, &newt);
786a1bf3f78SToomas Soome 	ch = getchar();
787a1bf3f78SToomas Soome 	tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
788a1bf3f78SToomas Soome 
789a1bf3f78SToomas Soome 	if (ch != -1)
790a1bf3f78SToomas Soome 		(void) ungetc(ch, stdin);
791a1bf3f78SToomas Soome 
792a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM),
793a1bf3f78SToomas Soome 	    ch != -1? FICL_TRUE : FICL_FALSE);
794a1bf3f78SToomas Soome #else
795a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM),
796a1bf3f78SToomas Soome 	    ischar()? FICL_TRUE : FICL_FALSE);
797a1bf3f78SToomas Soome #endif
798a1bf3f78SToomas Soome }
799a1bf3f78SToomas Soome 
800a1bf3f78SToomas Soome /*
801a1bf3f78SToomas Soome  * seconds - gives number of seconds since beginning of time
802a1bf3f78SToomas Soome  *
803a1bf3f78SToomas Soome  * beginning of time is defined as:
804a1bf3f78SToomas Soome  *
805a1bf3f78SToomas Soome  *	BTX	- number of seconds since midnight
806a1bf3f78SToomas Soome  *	FreeBSD	- number of seconds since Jan 1 1970
807a1bf3f78SToomas Soome  *
808a1bf3f78SToomas Soome  * seconds ( -- u )
809a1bf3f78SToomas Soome  */
810a1bf3f78SToomas Soome static void
811a1bf3f78SToomas Soome pseconds(ficlVm *pVM)
812a1bf3f78SToomas Soome {
813a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1);
814a1bf3f78SToomas Soome 
815a1bf3f78SToomas Soome 	ficlStackPushUnsigned(ficlVmGetDataStack(pVM),
816a1bf3f78SToomas Soome 	    (ficlUnsigned) time(NULL));
817a1bf3f78SToomas Soome }
818a1bf3f78SToomas Soome 
819a1bf3f78SToomas Soome /*
820a1bf3f78SToomas Soome  * ms - wait at least that many milliseconds (FACILITY)
821a1bf3f78SToomas Soome  * ms ( u -- )
822a1bf3f78SToomas Soome  */
823a1bf3f78SToomas Soome static void
824a1bf3f78SToomas Soome ms(ficlVm *pVM)
825a1bf3f78SToomas Soome {
826a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0);
827a1bf3f78SToomas Soome 
828*e09118e4SToomas Soome #ifndef _STANDALONE
829a1bf3f78SToomas Soome 	usleep(ficlStackPopUnsigned(ficlVmGetDataStack(pVM)) * 1000);
830a1bf3f78SToomas Soome #else
831a1bf3f78SToomas Soome 	delay(ficlStackPopUnsigned(ficlVmGetDataStack(pVM)) * 1000);
832a1bf3f78SToomas Soome #endif
833a1bf3f78SToomas Soome }
834a1bf3f78SToomas Soome 
835a1bf3f78SToomas Soome /*
836a1bf3f78SToomas Soome  * fkey - get a character from a file
837a1bf3f78SToomas Soome  * fkey ( file -- char )
838a1bf3f78SToomas Soome  */
839a1bf3f78SToomas Soome static void
840a1bf3f78SToomas Soome fkey(ficlVm *pVM)
841a1bf3f78SToomas Soome {
842a1bf3f78SToomas Soome 	int i, fd;
843a1bf3f78SToomas Soome 	char ch;
844a1bf3f78SToomas Soome 
845a1bf3f78SToomas Soome 	FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 1);
846a1bf3f78SToomas Soome 
847a1bf3f78SToomas Soome 	fd = ficlStackPopInteger(ficlVmGetDataStack(pVM));
848a1bf3f78SToomas Soome 	i = read(fd, &ch, 1);
849a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM), i > 0 ? ch : -1);
850a1bf3f78SToomas Soome }
851a1bf3f78SToomas Soome 
852a1bf3f78SToomas Soome /*
853a1bf3f78SToomas Soome  * Retrieves free space remaining on the dictionary
854a1bf3f78SToomas Soome  */
855a1bf3f78SToomas Soome static void
856a1bf3f78SToomas Soome freeHeap(ficlVm *pVM)
857a1bf3f78SToomas Soome {
858a1bf3f78SToomas Soome 	ficlStackPushInteger(ficlVmGetDataStack(pVM),
859a1bf3f78SToomas Soome 	    ficlDictionaryCellsAvailable(ficlVmGetDictionary(pVM)));
860a1bf3f78SToomas Soome }
861a1bf3f78SToomas Soome 
862a1bf3f78SToomas Soome /*
863a1bf3f78SToomas Soome  * f i c l C o m p i l e P l a t f o r m
864a1bf3f78SToomas Soome  * Build FreeBSD platform extensions into the system dictionary
865a1bf3f78SToomas Soome  */
866a1bf3f78SToomas Soome void
867a1bf3f78SToomas Soome ficlSystemCompilePlatform(ficlSystem *pSys)
868a1bf3f78SToomas Soome {
869a1bf3f78SToomas Soome 	ficlDictionary *dp = ficlSystemGetDictionary(pSys);
870a1bf3f78SToomas Soome 	ficlDictionary *env = ficlSystemGetEnvironment(pSys);
871*e09118e4SToomas Soome #ifdef _STANDALONE
872d5a0772bSToomas Soome 	ficlCompileFcn **fnpp;
873d5a0772bSToomas Soome #endif
874a1bf3f78SToomas Soome 
875a1bf3f78SToomas Soome 	FICL_SYSTEM_ASSERT(pSys, dp);
876a1bf3f78SToomas Soome 	FICL_SYSTEM_ASSERT(pSys, env);
877a1bf3f78SToomas Soome 
878a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, ".#", displayCellNoPad,
879a1bf3f78SToomas Soome 	    FICL_WORD_DEFAULT);
880a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "isdir?", isdirQuestion,
881a1bf3f78SToomas Soome 	    FICL_WORD_DEFAULT);
882a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "fopen", pfopen, FICL_WORD_DEFAULT);
883a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "fclose", pfclose, FICL_WORD_DEFAULT);
884a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "fread", pfread, FICL_WORD_DEFAULT);
885a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "fopendir", pfopendir,
886a1bf3f78SToomas Soome 	    FICL_WORD_DEFAULT);
887a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "freaddir", pfreaddir,
888a1bf3f78SToomas Soome 	    FICL_WORD_DEFAULT);
889a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "fclosedir", pfclosedir,
890a1bf3f78SToomas Soome 	    FICL_WORD_DEFAULT);
891a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "fload", pfload, FICL_WORD_DEFAULT);
892a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "fkey", fkey, FICL_WORD_DEFAULT);
893a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "fseek", pfseek, FICL_WORD_DEFAULT);
894a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "fwrite", pfwrite, FICL_WORD_DEFAULT);
895a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "key", key, FICL_WORD_DEFAULT);
896a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "key?", keyQuestion, FICL_WORD_DEFAULT);
897a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "ms", ms, FICL_WORD_DEFAULT);
898a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "seconds", pseconds, FICL_WORD_DEFAULT);
899a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "heap?", freeHeap, FICL_WORD_DEFAULT);
900a1bf3f78SToomas Soome 
901a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "setenv", ficlSetenv, FICL_WORD_DEFAULT);
902a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "setenv?", ficlSetenvq,
903a1bf3f78SToomas Soome 	    FICL_WORD_DEFAULT);
904a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "getenv", ficlGetenv, FICL_WORD_DEFAULT);
905a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "unsetenv", ficlUnsetenv,
906a1bf3f78SToomas Soome 	    FICL_WORD_DEFAULT);
907a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "copyin", ficlCopyin, FICL_WORD_DEFAULT);
908a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "copyout", ficlCopyout,
909a1bf3f78SToomas Soome 	    FICL_WORD_DEFAULT);
910a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "findfile", ficlFindfile,
911a1bf3f78SToomas Soome 	    FICL_WORD_DEFAULT);
912a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dp, "ccall", ficlCcall, FICL_WORD_DEFAULT);
913065446baSToomas Soome 	ficlDictionarySetPrimitive(dp, "uuid-from-string", ficlUuidFromString,
914065446baSToomas Soome 	    FICL_WORD_DEFAULT);
915065446baSToomas Soome 	ficlDictionarySetPrimitive(dp, "uuid-to-string", ficlUuidToString,
916065446baSToomas Soome 	    FICL_WORD_DEFAULT);
917*e09118e4SToomas Soome #ifdef _STANDALONE
918d5a0772bSToomas Soome 	/* Register words from linker set. */
919d5a0772bSToomas Soome 	SET_FOREACH(fnpp, Xficl_compile_set)
920d5a0772bSToomas Soome 		(*fnpp)(pSys);
921a1bf3f78SToomas Soome #endif
922a1bf3f78SToomas Soome 
923a1bf3f78SToomas Soome #if defined(__i386__) || defined(__amd64__)
924a1bf3f78SToomas Soome 	ficlDictionarySetConstant(env, "arch-i386", FICL_TRUE);
925a1bf3f78SToomas Soome 	ficlDictionarySetConstant(env, "arch-sparc", FICL_FALSE);
926a1bf3f78SToomas Soome #endif
927a1bf3f78SToomas Soome #ifdef __sparc
928a1bf3f78SToomas Soome 	ficlDictionarySetConstant(env, "arch-i386", FICL_FALSE);
929a1bf3f78SToomas Soome 	ficlDictionarySetConstant(env, "arch-sparc", FICL_TRUE);
930a1bf3f78SToomas Soome #endif
931a1bf3f78SToomas Soome }
932