161374Sdcs/*-
261374Sdcs * Copyright (c) 2000 Daniel Capo Sobral
361374Sdcs * All rights reserved.
461374Sdcs *
561374Sdcs * Redistribution and use in source and binary forms, with or without
661374Sdcs * modification, are permitted provided that the following conditions
761374Sdcs * are met:
861374Sdcs * 1. Redistributions of source code must retain the above copyright
961374Sdcs *    notice, this list of conditions and the following disclaimer.
1061374Sdcs * 2. Redistributions in binary form must reproduce the above copyright
1161374Sdcs *    notice, this list of conditions and the following disclaimer in the
1261374Sdcs *    documentation and/or other materials provided with the distribution.
1361374Sdcs *
1461374Sdcs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1561374Sdcs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1661374Sdcs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1761374Sdcs * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1861374Sdcs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1961374Sdcs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2061374Sdcs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2161374Sdcs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2261374Sdcs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2361374Sdcs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2461374Sdcs * SUCH DAMAGE.
2561374Sdcs *
2661374Sdcs *	$FreeBSD: releng/10.3/sys/boot/ficl/loader.c 254155 2013-08-09 19:10:56Z marcel $
2761374Sdcs */
2861374Sdcs
2961374Sdcs/*******************************************************************
3061374Sdcs** l o a d e r . c
3161374Sdcs** Additional FICL words designed for FreeBSD's loader
3261374Sdcs**
3361374Sdcs*******************************************************************/
3461374Sdcs
35102215Sscottl#ifdef TESTMAIN
36253862Smarcel#include <sys/types.h>
37253862Smarcel#include <sys/stat.h>
38253862Smarcel#include <dirent.h>
39253862Smarcel#include <fcntl.h>
40253862Smarcel#include <stdio.h>
41102215Sscottl#include <stdlib.h>
42253862Smarcel#include <unistd.h>
43102215Sscottl#else
4461374Sdcs#include <stand.h>
45102215Sscottl#endif
4661374Sdcs#include "bootstrap.h"
4761374Sdcs#include <string.h>
4861374Sdcs#include "ficl.h"
4961374Sdcs
5076116Sdcs/*		FreeBSD's loader interaction words and extras
5161374Sdcs *
5261374Sdcs * 		setenv      ( value n name n' -- )
5361374Sdcs * 		setenv?     ( value n name n' flag -- )
5461374Sdcs * 		getenv      ( addr n -- addr' n' | -1 )
5561374Sdcs * 		unsetenv    ( addr n -- )
5661374Sdcs * 		copyin      ( addr addr' len -- )
5761374Sdcs * 		copyout     ( addr addr' len -- )
5865617Sdcs * 		findfile    ( name len type len' -- addr )
5965617Sdcs * 		pnpdevices  ( -- addr )
6065617Sdcs * 		pnphandlers ( -- addr )
6165617Sdcs * 		ccall       ( [[...[p10] p9] ... p1] n addr -- result )
6276116Sdcs * 		.#	    ( value -- )
6361374Sdcs */
6461374Sdcs
6561374Sdcsvoid
6661374SdcsficlSetenv(FICL_VM *pVM)
6761374Sdcs{
68138223Sscottl#ifndef TESTMAIN
69138223Sscottl	char	*name, *value;
70138223Sscottl#endif
71138223Sscottl	char	*namep, *valuep;
7261374Sdcs	int	names, values;
7361374Sdcs
7461374Sdcs#if FICL_ROBUST > 1
7561374Sdcs	vmCheckStack(pVM, 4, 0);
7661374Sdcs#endif
7761374Sdcs	names = stackPopINT(pVM->pStack);
7861374Sdcs	namep = (char*) stackPopPtr(pVM->pStack);
7961374Sdcs	values = stackPopINT(pVM->pStack);
8061374Sdcs	valuep = (char*) stackPopPtr(pVM->pStack);
8161374Sdcs
82138223Sscottl#ifndef TESTMAIN
8361374Sdcs	name = (char*) ficlMalloc(names+1);
8461374Sdcs	if (!name)
8561374Sdcs		vmThrowErr(pVM, "Error: out of memory");
8661374Sdcs	strncpy(name, namep, names);
8761374Sdcs	name[names] = '\0';
8861374Sdcs	value = (char*) ficlMalloc(values+1);
8961374Sdcs	if (!value)
9061374Sdcs		vmThrowErr(pVM, "Error: out of memory");
9161374Sdcs	strncpy(value, valuep, values);
9261374Sdcs	value[values] = '\0';
9361374Sdcs
9461374Sdcs	setenv(name, value, 1);
9561374Sdcs	ficlFree(name);
9661374Sdcs	ficlFree(value);
97138223Sscottl#endif
9861374Sdcs
9961374Sdcs	return;
10061374Sdcs}
10161374Sdcs
10261374Sdcsvoid
10361374SdcsficlSetenvq(FICL_VM *pVM)
10461374Sdcs{
105138223Sscottl#ifndef TESTMAIN
106138223Sscottl	char	*name, *value;
107138223Sscottl#endif
108138223Sscottl	char	*namep, *valuep;
10961374Sdcs	int	names, values, overwrite;
11061374Sdcs
11161374Sdcs#if FICL_ROBUST > 1
11261374Sdcs	vmCheckStack(pVM, 5, 0);
11361374Sdcs#endif
11461374Sdcs	overwrite = stackPopINT(pVM->pStack);
11561374Sdcs	names = stackPopINT(pVM->pStack);
11661374Sdcs	namep = (char*) stackPopPtr(pVM->pStack);
11761374Sdcs	values = stackPopINT(pVM->pStack);
11861374Sdcs	valuep = (char*) stackPopPtr(pVM->pStack);
11961374Sdcs
120138223Sscottl#ifndef TESTMAIN
12161374Sdcs	name = (char*) ficlMalloc(names+1);
12261374Sdcs	if (!name)
12361374Sdcs		vmThrowErr(pVM, "Error: out of memory");
12461374Sdcs	strncpy(name, namep, names);
12561374Sdcs	name[names] = '\0';
12661374Sdcs	value = (char*) ficlMalloc(values+1);
12761374Sdcs	if (!value)
12861374Sdcs		vmThrowErr(pVM, "Error: out of memory");
12961374Sdcs	strncpy(value, valuep, values);
13061374Sdcs	value[values] = '\0';
13161374Sdcs
13261374Sdcs	setenv(name, value, overwrite);
13361374Sdcs	ficlFree(name);
13461374Sdcs	ficlFree(value);
135138223Sscottl#endif
13661374Sdcs
13761374Sdcs	return;
13861374Sdcs}
13961374Sdcs
14061374Sdcsvoid
14161374SdcsficlGetenv(FICL_VM *pVM)
14261374Sdcs{
143138223Sscottl#ifndef TESTMAIN
144253862Smarcel	char	*name, *value;
145138223Sscottl#endif
146253862Smarcel	char	*namep;
14761374Sdcs	int	names;
14861374Sdcs
14961374Sdcs#if FICL_ROBUST > 1
15061374Sdcs	vmCheckStack(pVM, 2, 2);
15161374Sdcs#endif
15261374Sdcs	names = stackPopINT(pVM->pStack);
15361374Sdcs	namep = (char*) stackPopPtr(pVM->pStack);
15461374Sdcs
155138223Sscottl#ifndef TESTMAIN
15661374Sdcs	name = (char*) ficlMalloc(names+1);
15761374Sdcs	if (!name)
15861374Sdcs		vmThrowErr(pVM, "Error: out of memory");
15961374Sdcs	strncpy(name, namep, names);
16061374Sdcs	name[names] = '\0';
16161374Sdcs
16261374Sdcs	value = getenv(name);
16361374Sdcs	ficlFree(name);
16461374Sdcs
16561374Sdcs	if(value != NULL) {
16661374Sdcs		stackPushPtr(pVM->pStack, value);
16761374Sdcs		stackPushINT(pVM->pStack, strlen(value));
16861374Sdcs	} else
169138223Sscottl#endif
17061374Sdcs		stackPushINT(pVM->pStack, -1);
17161374Sdcs
17261374Sdcs	return;
17361374Sdcs}
17461374Sdcs
17561374Sdcsvoid
17661374SdcsficlUnsetenv(FICL_VM *pVM)
17761374Sdcs{
178138223Sscottl#ifndef TESTMAIN
179138223Sscottl	char	*name;
180138223Sscottl#endif
181138223Sscottl	char	*namep;
18261374Sdcs	int	names;
18361374Sdcs
18461374Sdcs#if FICL_ROBUST > 1
18561374Sdcs	vmCheckStack(pVM, 2, 0);
18661374Sdcs#endif
18761374Sdcs	names = stackPopINT(pVM->pStack);
18861374Sdcs	namep = (char*) stackPopPtr(pVM->pStack);
18961374Sdcs
190138223Sscottl#ifndef TESTMAIN
19161374Sdcs	name = (char*) ficlMalloc(names+1);
19261374Sdcs	if (!name)
19361374Sdcs		vmThrowErr(pVM, "Error: out of memory");
19461374Sdcs	strncpy(name, namep, names);
19561374Sdcs	name[names] = '\0';
19661374Sdcs
19761374Sdcs	unsetenv(name);
19861374Sdcs	ficlFree(name);
199138223Sscottl#endif
20061374Sdcs
20161374Sdcs	return;
20261374Sdcs}
20361374Sdcs
20461374Sdcsvoid
20561374SdcsficlCopyin(FICL_VM *pVM)
20661374Sdcs{
20761374Sdcs	void*		src;
20861374Sdcs	vm_offset_t	dest;
20961374Sdcs	size_t		len;
21061374Sdcs
21161374Sdcs#if FICL_ROBUST > 1
21261374Sdcs	vmCheckStack(pVM, 3, 0);
21361374Sdcs#endif
21461374Sdcs
21561374Sdcs	len = stackPopINT(pVM->pStack);
21661374Sdcs	dest = stackPopINT(pVM->pStack);
21761374Sdcs	src = stackPopPtr(pVM->pStack);
21861374Sdcs
219138223Sscottl#ifndef TESTMAIN
22061374Sdcs	archsw.arch_copyin(src, dest, len);
221138223Sscottl#endif
22261374Sdcs
22361374Sdcs	return;
22461374Sdcs}
22561374Sdcs
22661374Sdcsvoid
22761374SdcsficlCopyout(FICL_VM *pVM)
22861374Sdcs{
22961374Sdcs	void*		dest;
23061374Sdcs	vm_offset_t	src;
23161374Sdcs	size_t		len;
23261374Sdcs
23361374Sdcs#if FICL_ROBUST > 1
23461374Sdcs	vmCheckStack(pVM, 3, 0);
23561374Sdcs#endif
23661374Sdcs
23761374Sdcs	len = stackPopINT(pVM->pStack);
23861374Sdcs	dest = stackPopPtr(pVM->pStack);
23961374Sdcs	src = stackPopINT(pVM->pStack);
24061374Sdcs
241138223Sscottl#ifndef TESTMAIN
24261374Sdcs	archsw.arch_copyout(src, dest, len);
243138223Sscottl#endif
24461374Sdcs
24561374Sdcs	return;
24661374Sdcs}
24761374Sdcs
24865617Sdcsvoid
24965617SdcsficlFindfile(FICL_VM *pVM)
25065617Sdcs{
251138223Sscottl#ifndef TESTMAIN
252253862Smarcel	char	*name, *type;
253138223Sscottl#endif
254253862Smarcel	char	*namep, *typep;
25565617Sdcs	struct	preloaded_file* fp;
25665617Sdcs	int	names, types;
25765617Sdcs
25865617Sdcs#if FICL_ROBUST > 1
25965617Sdcs	vmCheckStack(pVM, 4, 1);
26065617Sdcs#endif
26165617Sdcs
26265617Sdcs	types = stackPopINT(pVM->pStack);
26365617Sdcs	typep = (char*) stackPopPtr(pVM->pStack);
26465617Sdcs	names = stackPopINT(pVM->pStack);
26565617Sdcs	namep = (char*) stackPopPtr(pVM->pStack);
266138223Sscottl#ifndef TESTMAIN
26765617Sdcs	name = (char*) ficlMalloc(names+1);
26865617Sdcs	if (!name)
26965617Sdcs		vmThrowErr(pVM, "Error: out of memory");
27065617Sdcs	strncpy(name, namep, names);
27165617Sdcs	name[names] = '\0';
27265617Sdcs	type = (char*) ficlMalloc(types+1);
27365617Sdcs	if (!type)
27465617Sdcs		vmThrowErr(pVM, "Error: out of memory");
27565617Sdcs	strncpy(type, typep, types);
27665617Sdcs	type[types] = '\0';
27765617Sdcs
27865617Sdcs	fp = file_findfile(name, type);
279138223Sscottl#else
280138223Sscottl	fp = NULL;
281138223Sscottl#endif
28265617Sdcs	stackPushPtr(pVM->pStack, fp);
28365617Sdcs
28465617Sdcs	return;
28565617Sdcs}
28665617Sdcs
287138223Sscottl#ifndef TESTMAIN
28865677Sdfr#ifdef HAVE_PNP
28965677Sdfr
29065617Sdcsvoid
29165617SdcsficlPnpdevices(FICL_VM *pVM)
29265617Sdcs{
29365617Sdcs	static int pnp_devices_initted = 0;
29465617Sdcs#if FICL_ROBUST > 1
29565617Sdcs	vmCheckStack(pVM, 0, 1);
29665617Sdcs#endif
29765617Sdcs
29865617Sdcs	if(!pnp_devices_initted) {
29965617Sdcs		STAILQ_INIT(&pnp_devices);
30065617Sdcs		pnp_devices_initted = 1;
30165617Sdcs	}
30265617Sdcs
30365617Sdcs	stackPushPtr(pVM->pStack, &pnp_devices);
30465617Sdcs
30565617Sdcs	return;
30665617Sdcs}
30765617Sdcs
30865617Sdcsvoid
30965617SdcsficlPnphandlers(FICL_VM *pVM)
31065617Sdcs{
31165617Sdcs#if FICL_ROBUST > 1
31265617Sdcs	vmCheckStack(pVM, 0, 1);
31365617Sdcs#endif
31465617Sdcs
31565617Sdcs	stackPushPtr(pVM->pStack, pnphandlers);
31665617Sdcs
31765617Sdcs	return;
31865617Sdcs}
31965617Sdcs
32065677Sdfr#endif
32165677Sdfr
32276116Sdcs#endif /* ndef TESTMAIN */
32376116Sdcs
32465617Sdcsvoid
32565617SdcsficlCcall(FICL_VM *pVM)
32665617Sdcs{
32765617Sdcs	int (*func)(int, ...);
32865617Sdcs	int result, p[10];
32965617Sdcs	int nparam, i;
33065617Sdcs
33165617Sdcs#if FICL_ROBUST > 1
33265617Sdcs	vmCheckStack(pVM, 2, 0);
33365617Sdcs#endif
33465617Sdcs
33565617Sdcs	func = stackPopPtr(pVM->pStack);
33665617Sdcs	nparam = stackPopINT(pVM->pStack);
33765617Sdcs
33865617Sdcs#if FICL_ROBUST > 1
33965617Sdcs	vmCheckStack(pVM, nparam, 1);
34065617Sdcs#endif
34165617Sdcs
34265617Sdcs	for (i = 0; i < nparam; i++)
34365617Sdcs		p[i] = stackPopINT(pVM->pStack);
34465617Sdcs
34565617Sdcs	result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
34665617Sdcs	    p[9]);
34765617Sdcs
34865617Sdcs	stackPushINT(pVM->pStack, result);
34965617Sdcs
35065617Sdcs	return;
35165617Sdcs}
35265617Sdcs
35376116Sdcs/**************************************************************************
35476116Sdcs                        f i c l E x e c F D
35576116Sdcs** reads in text from file fd and passes it to ficlExec()
35676116Sdcs * returns VM_OUTOFTEXT on success or the ficlExec() error code on
35776116Sdcs * failure.
35876116Sdcs */
35976116Sdcs#define nLINEBUF 256
36076116Sdcsint ficlExecFD(FICL_VM *pVM, int fd)
36176116Sdcs{
36276116Sdcs    char    cp[nLINEBUF];
36376116Sdcs    int     nLine = 0, rval = VM_OUTOFTEXT;
36476116Sdcs    char    ch;
36576116Sdcs    CELL    id;
36676116Sdcs
36776116Sdcs    id = pVM->sourceID;
36876116Sdcs    pVM->sourceID.i = fd;
36976116Sdcs
37076116Sdcs    /* feed each line to ficlExec */
37176116Sdcs    while (1) {
37276116Sdcs	int status, i;
37376116Sdcs
37476116Sdcs	i = 0;
37576116Sdcs	while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
37676116Sdcs	    cp[i++] = ch;
37776116Sdcs        nLine++;
37876116Sdcs	if (!i) {
37976116Sdcs	    if (status < 1)
38076116Sdcs		break;
38176116Sdcs	    continue;
38276116Sdcs	}
38376116Sdcs        rval = ficlExecC(pVM, cp, i);
38476116Sdcs	if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT)
38576116Sdcs        {
38676116Sdcs            pVM->sourceID = id;
38776116Sdcs            return rval;
38876116Sdcs        }
38976116Sdcs    }
39076116Sdcs    /*
39176116Sdcs    ** Pass an empty line with SOURCE-ID == -1 to flush
39276116Sdcs    ** any pending REFILLs (as required by FILE wordset)
39376116Sdcs    */
39476116Sdcs    pVM->sourceID.i = -1;
39576116Sdcs    ficlExec(pVM, "");
39676116Sdcs
39776116Sdcs    pVM->sourceID = id;
39876116Sdcs    return rval;
39976116Sdcs}
40076116Sdcs
40176116Sdcsstatic void displayCellNoPad(FICL_VM *pVM)
40276116Sdcs{
40376116Sdcs    CELL c;
40476116Sdcs#if FICL_ROBUST > 1
40576116Sdcs    vmCheckStack(pVM, 1, 0);
40676116Sdcs#endif
40776116Sdcs    c = stackPop(pVM->pStack);
40876116Sdcs    ltoa((c).i, pVM->pad, pVM->base);
40976116Sdcs    vmTextOut(pVM, pVM->pad, 0);
41076116Sdcs    return;
41176116Sdcs}
41276116Sdcs
413253172Smarcel/*      isdir? - Return whether an fd corresponds to a directory.
414253172Smarcel *
415253172Smarcel * isdir? ( fd -- bool )
416253172Smarcel */
417253172Smarcelstatic void isdirQuestion(FICL_VM *pVM)
418253172Smarcel{
419253172Smarcel    struct stat sb;
420253172Smarcel    FICL_INT flag;
421253172Smarcel    int fd;
422253172Smarcel
423253172Smarcel#if FICL_ROBUST > 1
424253172Smarcel    vmCheckStack(pVM, 1, 1);
425253172Smarcel#endif
426253172Smarcel
427253172Smarcel    fd = stackPopINT(pVM->pStack);
428253172Smarcel    flag = FICL_FALSE;
429253172Smarcel    do {
430253172Smarcel        if (fd < 0)
431253172Smarcel            break;
432253172Smarcel        if (fstat(fd, &sb) < 0)
433253172Smarcel            break;
434253172Smarcel        if (!S_ISDIR(sb.st_mode))
435253172Smarcel            break;
436253172Smarcel        flag = FICL_TRUE;
437253172Smarcel    } while (0);
438253172Smarcel    stackPushINT(pVM->pStack, flag);
439253172Smarcel}
440253172Smarcel
44176116Sdcs/*          fopen - open a file and return new fd on stack.
44276116Sdcs *
44387636Sjhb * fopen ( ptr count mode -- fd )
44476116Sdcs */
44576116Sdcsstatic void pfopen(FICL_VM *pVM)
44676116Sdcs{
44787636Sjhb    int     mode, fd, count;
44887636Sjhb    char    *ptr, *name;
44976116Sdcs
45076116Sdcs#if FICL_ROBUST > 1
45187636Sjhb    vmCheckStack(pVM, 3, 1);
45276116Sdcs#endif
45387636Sjhb
45487636Sjhb    mode = stackPopINT(pVM->pStack);    /* get mode */
45587636Sjhb    count = stackPopINT(pVM->pStack);   /* get count */
45687636Sjhb    ptr = stackPopPtr(pVM->pStack);     /* get ptr */
45787636Sjhb
45887636Sjhb    if ((count < 0) || (ptr == NULL)) {
45987636Sjhb        stackPushINT(pVM->pStack, -1);
46087636Sjhb        return;
46187636Sjhb    }
46287636Sjhb
46387636Sjhb    /* ensure that the string is null terminated */
46487636Sjhb    name = (char *)malloc(count+1);
46587636Sjhb    bcopy(ptr,name,count);
46687636Sjhb    name[count] = 0;
46787636Sjhb
46887636Sjhb    /* open the file */
46987636Sjhb    fd = open(name, mode);
47087636Sjhb    free(name);
47176116Sdcs    stackPushINT(pVM->pStack, fd);
47276116Sdcs    return;
47387636Sjhb}
47476116Sdcs
47576116Sdcs/*          fclose - close a file who's fd is on stack.
47676116Sdcs *
47776116Sdcs * fclose ( fd -- )
47876116Sdcs */
47976116Sdcsstatic void pfclose(FICL_VM *pVM)
48076116Sdcs{
48176116Sdcs    int fd;
48276116Sdcs
48376116Sdcs#if FICL_ROBUST > 1
48476116Sdcs    vmCheckStack(pVM, 1, 0);
48576116Sdcs#endif
48676116Sdcs    fd = stackPopINT(pVM->pStack); /* get fd */
48776116Sdcs    if (fd != -1)
48876116Sdcs	close(fd);
48976116Sdcs    return;
49076116Sdcs}
49176116Sdcs
49276116Sdcs/*          fread - read file contents
49376116Sdcs *
49476116Sdcs * fread  ( fd buf nbytes  -- nread )
49576116Sdcs */
49676116Sdcsstatic void pfread(FICL_VM *pVM)
49776116Sdcs{
49876116Sdcs    int     fd, len;
49976116Sdcs    char *buf;
50076116Sdcs
50176116Sdcs#if FICL_ROBUST > 1
50276116Sdcs    vmCheckStack(pVM, 3, 1);
50376116Sdcs#endif
50476116Sdcs    len = stackPopINT(pVM->pStack); /* get number of bytes to read */
50576116Sdcs    buf = stackPopPtr(pVM->pStack); /* get buffer */
50676116Sdcs    fd = stackPopINT(pVM->pStack); /* get fd */
50776116Sdcs    if (len > 0 && buf && fd != -1)
50876116Sdcs	stackPushINT(pVM->pStack, read(fd, buf, len));
50976116Sdcs    else
51076116Sdcs	stackPushINT(pVM->pStack, -1);
51176116Sdcs    return;
51276116Sdcs}
51376116Sdcs
514253172Smarcel/*      freaddir - read directory contents
515253172Smarcel *
516253172Smarcel * freaddir ( fd -- ptr len TRUE | FALSE )
517253172Smarcel */
518253172Smarcelstatic void pfreaddir(FICL_VM *pVM)
519253172Smarcel{
520253862Smarcel#ifdef TESTMAIN
521254155Smarcel    static struct dirent dirent;
522254155Smarcel    struct stat sb;
523254155Smarcel    char *buf;
524254155Smarcel    off_t off, ptr;
525254155Smarcel    u_int blksz;
526254155Smarcel    int bufsz;
527253862Smarcel#endif
528253172Smarcel    struct dirent *d;
529253172Smarcel    int fd;
530253172Smarcel
531253172Smarcel#if FICL_ROBUST > 1
532253172Smarcel    vmCheckStack(pVM, 1, 3);
533253172Smarcel#endif
534253172Smarcel
535253172Smarcel    fd = stackPopINT(pVM->pStack);
536253862Smarcel#if TESTMAIN
537253862Smarcel    /*
538253862Smarcel     * The readdirfd() function is specific to the loader environment.
539253862Smarcel     * We do the best we can to make freaddir work, but it's not at
540253862Smarcel     * all guaranteed.
541253862Smarcel     */
542254155Smarcel    d = NULL;
543254155Smarcel    buf = NULL;
544254155Smarcel    do {
545254155Smarcel	if (fd == -1)
546254155Smarcel	    break;
547254155Smarcel	if (fstat(fd, &sb) == -1)
548254155Smarcel	    break;
549254155Smarcel	blksz = (sb.st_blksize) ? sb.st_blksize : getpagesize();
550254155Smarcel	if ((blksz & (blksz - 1)) != 0)
551254155Smarcel	    break;
552254155Smarcel	buf = malloc(blksz);
553254155Smarcel	if (buf == NULL)
554254155Smarcel	    break;
555254155Smarcel	off = lseek(fd, 0LL, SEEK_CUR);
556254155Smarcel	if (off == -1)
557254155Smarcel	    break;
558254155Smarcel	ptr = off;
559254155Smarcel	if (lseek(fd, 0, SEEK_SET) == -1)
560254155Smarcel	    break;
561254155Smarcel	bufsz = getdents(fd, buf, blksz);
562254155Smarcel	while (bufsz > 0 && bufsz <= ptr) {
563254155Smarcel	    ptr -= bufsz;
564254155Smarcel	    bufsz = getdents(fd, buf, blksz);
565254155Smarcel	}
566254155Smarcel	if (bufsz <= 0)
567254155Smarcel	    break;
568254155Smarcel	d = (void *)(buf + ptr);
569254155Smarcel	dirent = *d;
570254155Smarcel	off += d->d_reclen;
571254155Smarcel	d = (lseek(fd, off, SEEK_SET) != off) ? NULL : &dirent;
572254155Smarcel    } while (0);
573254155Smarcel    if (buf != NULL)
574254155Smarcel	free(buf);
575253862Smarcel#else
576253172Smarcel    d = readdirfd(fd);
577253862Smarcel#endif
578253172Smarcel    if (d != NULL) {
579253172Smarcel        stackPushPtr(pVM->pStack, d->d_name);
580253172Smarcel        stackPushINT(pVM->pStack, strlen(d->d_name));
581253172Smarcel        stackPushINT(pVM->pStack, FICL_TRUE);
582253172Smarcel    } else {
583253172Smarcel        stackPushINT(pVM->pStack, FICL_FALSE);
584253172Smarcel    }
585253172Smarcel}
586253172Smarcel
58776116Sdcs/*          fload - interpret file contents
58876116Sdcs *
58976116Sdcs * fload  ( fd -- )
59076116Sdcs */
59176116Sdcsstatic void pfload(FICL_VM *pVM)
59276116Sdcs{
59376116Sdcs    int     fd;
59476116Sdcs
59576116Sdcs#if FICL_ROBUST > 1
59676116Sdcs    vmCheckStack(pVM, 1, 0);
59776116Sdcs#endif
59876116Sdcs    fd = stackPopINT(pVM->pStack); /* get fd */
59976116Sdcs    if (fd != -1)
60076116Sdcs	ficlExecFD(pVM, fd);
60176116Sdcs    return;
60276116Sdcs}
60376116Sdcs
60487636Sjhb/*          fwrite - write file contents
60587636Sjhb *
60687636Sjhb * fwrite  ( fd buf nbytes  -- nwritten )
60787636Sjhb */
60887636Sjhbstatic void pfwrite(FICL_VM *pVM)
60987636Sjhb{
61087636Sjhb    int     fd, len;
61187636Sjhb    char *buf;
61287636Sjhb
61387636Sjhb#if FICL_ROBUST > 1
61487636Sjhb    vmCheckStack(pVM, 3, 1);
61587636Sjhb#endif
61687636Sjhb    len = stackPopINT(pVM->pStack); /* get number of bytes to read */
61787636Sjhb    buf = stackPopPtr(pVM->pStack); /* get buffer */
61887636Sjhb    fd = stackPopINT(pVM->pStack); /* get fd */
61987636Sjhb    if (len > 0 && buf && fd != -1)
62087636Sjhb	stackPushINT(pVM->pStack, write(fd, buf, len));
62187636Sjhb    else
62287636Sjhb	stackPushINT(pVM->pStack, -1);
62387636Sjhb    return;
62487636Sjhb}
62587636Sjhb
62687636Sjhb/*          fseek - seek to a new position in a file
62787636Sjhb *
62887636Sjhb * fseek  ( fd ofs whence  -- pos )
62987636Sjhb */
63087636Sjhbstatic void pfseek(FICL_VM *pVM)
63187636Sjhb{
63287636Sjhb    int     fd, pos, whence;
63387636Sjhb
63487636Sjhb#if FICL_ROBUST > 1
63587636Sjhb    vmCheckStack(pVM, 3, 1);
63687636Sjhb#endif
63787636Sjhb    whence = stackPopINT(pVM->pStack);
63887636Sjhb    pos = stackPopINT(pVM->pStack);
63987636Sjhb    fd = stackPopINT(pVM->pStack);
64087636Sjhb    stackPushINT(pVM->pStack, lseek(fd, pos, whence));
64187636Sjhb    return;
64287636Sjhb}
64387636Sjhb
64476116Sdcs/*           key - get a character from stdin
64576116Sdcs *
64676116Sdcs * key ( -- char )
64776116Sdcs */
64876116Sdcsstatic void key(FICL_VM *pVM)
64976116Sdcs{
65076116Sdcs#if FICL_ROBUST > 1
65176116Sdcs    vmCheckStack(pVM, 0, 1);
65276116Sdcs#endif
65376116Sdcs    stackPushINT(pVM->pStack, getchar());
65476116Sdcs    return;
65576116Sdcs}
65676116Sdcs
65776116Sdcs/*           key? - check for a character from stdin (FACILITY)
65876116Sdcs *
65976116Sdcs * key? ( -- flag )
66076116Sdcs */
66176116Sdcsstatic void keyQuestion(FICL_VM *pVM)
66276116Sdcs{
66376116Sdcs#if FICL_ROBUST > 1
66476116Sdcs    vmCheckStack(pVM, 0, 1);
66576116Sdcs#endif
66676116Sdcs#ifdef TESTMAIN
66776116Sdcs    /* XXX Since we don't fiddle with termios, let it always succeed... */
66876116Sdcs    stackPushINT(pVM->pStack, FICL_TRUE);
66976116Sdcs#else
67076116Sdcs    /* But here do the right thing. */
67176116Sdcs    stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE);
67276116Sdcs#endif
67376116Sdcs    return;
67476116Sdcs}
67576116Sdcs
67676116Sdcs/* seconds - gives number of seconds since beginning of time
67776116Sdcs *
67876116Sdcs * beginning of time is defined as:
67976116Sdcs *
68076116Sdcs *	BTX	- number of seconds since midnight
68176116Sdcs *	FreeBSD	- number of seconds since Jan 1 1970
68276116Sdcs *
68376116Sdcs * seconds ( -- u )
68476116Sdcs */
68576116Sdcsstatic void pseconds(FICL_VM *pVM)
68676116Sdcs{
68776116Sdcs#if FICL_ROBUST > 1
68876116Sdcs    vmCheckStack(pVM,0,1);
68976116Sdcs#endif
69076116Sdcs    stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL));
69176116Sdcs    return;
69276116Sdcs}
69376116Sdcs
69476116Sdcs/* ms - wait at least that many milliseconds (FACILITY)
69576116Sdcs *
69676116Sdcs * ms ( u -- )
69776116Sdcs *
69876116Sdcs */
69976116Sdcsstatic void ms(FICL_VM *pVM)
70076116Sdcs{
70176116Sdcs#if FICL_ROBUST > 1
70276116Sdcs    vmCheckStack(pVM,1,0);
70376116Sdcs#endif
70476116Sdcs#ifdef TESTMAIN
70576116Sdcs    usleep(stackPopUNS(pVM->pStack)*1000);
70676116Sdcs#else
70776116Sdcs    delay(stackPopUNS(pVM->pStack)*1000);
70876116Sdcs#endif
70976116Sdcs    return;
71076116Sdcs}
71176116Sdcs
71276116Sdcs/*           fkey - get a character from a file
71376116Sdcs *
71476116Sdcs * fkey ( file -- char )
71576116Sdcs */
71676116Sdcsstatic void fkey(FICL_VM *pVM)
71776116Sdcs{
71876116Sdcs    int i, fd;
71976116Sdcs    char ch;
72076116Sdcs
72176116Sdcs#if FICL_ROBUST > 1
72276116Sdcs    vmCheckStack(pVM, 1, 1);
72376116Sdcs#endif
72476116Sdcs    fd = stackPopINT(pVM->pStack);
72576116Sdcs    i = read(fd, &ch, 1);
72676116Sdcs    stackPushINT(pVM->pStack, i > 0 ? ch : -1);
72776116Sdcs    return;
72876116Sdcs}
72976116Sdcs
73076116Sdcs/*
73176116Sdcs** Retrieves free space remaining on the dictionary
73276116Sdcs*/
73376116Sdcs
73476116Sdcsstatic void freeHeap(FICL_VM *pVM)
73576116Sdcs{
73694290Sdcs    stackPushINT(pVM->pStack, dictCellsAvail(ficlGetDict(pVM->pSys)));
73776116Sdcs}
73876116Sdcs
73976116Sdcs
74076116Sdcs/******************* Increase dictionary size on-demand ******************/
74176116Sdcs
74276116Sdcsstatic void ficlDictThreshold(FICL_VM *pVM)
74376116Sdcs{
74476116Sdcs    stackPushPtr(pVM->pStack, &dictThreshold);
74576116Sdcs}
74676116Sdcs
74776116Sdcsstatic void ficlDictIncrease(FICL_VM *pVM)
74876116Sdcs{
74976116Sdcs    stackPushPtr(pVM->pStack, &dictIncrease);
75076116Sdcs}
75176116Sdcs
75276116Sdcs
75376116Sdcs/**************************************************************************
75476116Sdcs                        f i c l C o m p i l e P l a t f o r m
75576116Sdcs** Build FreeBSD platform extensions into the system dictionary
75676116Sdcs**************************************************************************/
75776116Sdcsvoid ficlCompilePlatform(FICL_SYSTEM *pSys)
75876116Sdcs{
75976116Sdcs    FICL_DICT *dp = pSys->dp;
76076116Sdcs    assert (dp);
76176116Sdcs
76276116Sdcs    dictAppendWord(dp, ".#",        displayCellNoPad,    FW_DEFAULT);
763253172Smarcel    dictAppendWord(dp, "isdir?",    isdirQuestion,  FW_DEFAULT);
76476116Sdcs    dictAppendWord(dp, "fopen",	    pfopen,	    FW_DEFAULT);
76576116Sdcs    dictAppendWord(dp, "fclose",    pfclose,	    FW_DEFAULT);
76676116Sdcs    dictAppendWord(dp, "fread",	    pfread,	    FW_DEFAULT);
767253172Smarcel    dictAppendWord(dp, "freaddir",  pfreaddir,	    FW_DEFAULT);
76876116Sdcs    dictAppendWord(dp, "fload",	    pfload,	    FW_DEFAULT);
76976116Sdcs    dictAppendWord(dp, "fkey",	    fkey,	    FW_DEFAULT);
77087636Sjhb    dictAppendWord(dp, "fseek",     pfseek,	    FW_DEFAULT);
77187636Sjhb    dictAppendWord(dp, "fwrite",    pfwrite,	    FW_DEFAULT);
77276116Sdcs    dictAppendWord(dp, "key",	    key,	    FW_DEFAULT);
77376116Sdcs    dictAppendWord(dp, "key?",	    keyQuestion,    FW_DEFAULT);
77476116Sdcs    dictAppendWord(dp, "ms",        ms,             FW_DEFAULT);
77576116Sdcs    dictAppendWord(dp, "seconds",   pseconds,       FW_DEFAULT);
77676116Sdcs    dictAppendWord(dp, "heap?",     freeHeap,       FW_DEFAULT);
77776116Sdcs    dictAppendWord(dp, "dictthreshold", ficlDictThreshold, FW_DEFAULT);
77876116Sdcs    dictAppendWord(dp, "dictincrease", ficlDictIncrease, FW_DEFAULT);
77976116Sdcs
78076116Sdcs    dictAppendWord(dp, "setenv",    ficlSetenv,	    FW_DEFAULT);
78176116Sdcs    dictAppendWord(dp, "setenv?",   ficlSetenvq,    FW_DEFAULT);
78276116Sdcs    dictAppendWord(dp, "getenv",    ficlGetenv,	    FW_DEFAULT);
78376116Sdcs    dictAppendWord(dp, "unsetenv",  ficlUnsetenv,   FW_DEFAULT);
78476116Sdcs    dictAppendWord(dp, "copyin",    ficlCopyin,	    FW_DEFAULT);
78576116Sdcs    dictAppendWord(dp, "copyout",   ficlCopyout,    FW_DEFAULT);
78676116Sdcs    dictAppendWord(dp, "findfile",  ficlFindfile,   FW_DEFAULT);
787138223Sscottl    dictAppendWord(dp, "ccall",	    ficlCcall,	    FW_DEFAULT);
788138223Sscottl#ifndef TESTMAIN
789138223Sscottl#ifdef __i386__
790138223Sscottl    dictAppendWord(dp, "outb",      ficlOutb,       FW_DEFAULT);
791138223Sscottl    dictAppendWord(dp, "inb",       ficlInb,        FW_DEFAULT);
792138223Sscottl#endif
79376116Sdcs#ifdef HAVE_PNP
79476116Sdcs    dictAppendWord(dp, "pnpdevices",ficlPnpdevices, FW_DEFAULT);
79576116Sdcs    dictAppendWord(dp, "pnphandlers",ficlPnphandlers, FW_DEFAULT);
79676116Sdcs#endif
79776116Sdcs#endif
79876116Sdcs
799116000Snyan#if defined(PC98)
800116000Snyan    ficlSetEnv(pSys, "arch-pc98",         FICL_TRUE);
801116000Snyan#elif defined(__i386__)
80294290Sdcs    ficlSetEnv(pSys, "arch-i386",         FICL_TRUE);
80394290Sdcs    ficlSetEnv(pSys, "arch-ia64",         FICL_FALSE);
804123373Sgrehan    ficlSetEnv(pSys, "arch-powerpc",      FICL_FALSE);
80582941Sdfr#elif defined(__ia64__)
80694290Sdcs    ficlSetEnv(pSys, "arch-i386",         FICL_FALSE);
80794290Sdcs    ficlSetEnv(pSys, "arch-ia64",         FICL_TRUE);
808123373Sgrehan    ficlSetEnv(pSys, "arch-powerpc",      FICL_FALSE);
809123373Sgrehan#elif defined(__powerpc__)
810123373Sgrehan    ficlSetEnv(pSys, "arch-i386",         FICL_FALSE);
811123373Sgrehan    ficlSetEnv(pSys, "arch-ia64",         FICL_FALSE);
812123373Sgrehan    ficlSetEnv(pSys, "arch-powerpc",      FICL_TRUE);
81376116Sdcs#endif
81476116Sdcs
81576116Sdcs    return;
81676116Sdcs}
81776116Sdcs
818