1/*-
2 * Copyright (c) 2000 Daniel Capo Sobral
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *	$FreeBSD: releng/10.3/sys/boot/ficl/loader.c 254155 2013-08-09 19:10:56Z marcel $
27 */
28
29/*******************************************************************
30** l o a d e r . c
31** Additional FICL words designed for FreeBSD's loader
32**
33*******************************************************************/
34
35#ifdef TESTMAIN
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <dirent.h>
39#include <fcntl.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <unistd.h>
43#else
44#include <stand.h>
45#endif
46#include "bootstrap.h"
47#include <string.h>
48#include "ficl.h"
49
50/*		FreeBSD's loader interaction words and extras
51 *
52 * 		setenv      ( value n name n' -- )
53 * 		setenv?     ( value n name n' flag -- )
54 * 		getenv      ( addr n -- addr' n' | -1 )
55 * 		unsetenv    ( addr n -- )
56 * 		copyin      ( addr addr' len -- )
57 * 		copyout     ( addr addr' len -- )
58 * 		findfile    ( name len type len' -- addr )
59 * 		pnpdevices  ( -- addr )
60 * 		pnphandlers ( -- addr )
61 * 		ccall       ( [[...[p10] p9] ... p1] n addr -- result )
62 * 		.#	    ( value -- )
63 */
64
65void
66ficlSetenv(FICL_VM *pVM)
67{
68#ifndef TESTMAIN
69	char	*name, *value;
70#endif
71	char	*namep, *valuep;
72	int	names, values;
73
74#if FICL_ROBUST > 1
75	vmCheckStack(pVM, 4, 0);
76#endif
77	names = stackPopINT(pVM->pStack);
78	namep = (char*) stackPopPtr(pVM->pStack);
79	values = stackPopINT(pVM->pStack);
80	valuep = (char*) stackPopPtr(pVM->pStack);
81
82#ifndef TESTMAIN
83	name = (char*) ficlMalloc(names+1);
84	if (!name)
85		vmThrowErr(pVM, "Error: out of memory");
86	strncpy(name, namep, names);
87	name[names] = '\0';
88	value = (char*) ficlMalloc(values+1);
89	if (!value)
90		vmThrowErr(pVM, "Error: out of memory");
91	strncpy(value, valuep, values);
92	value[values] = '\0';
93
94	setenv(name, value, 1);
95	ficlFree(name);
96	ficlFree(value);
97#endif
98
99	return;
100}
101
102void
103ficlSetenvq(FICL_VM *pVM)
104{
105#ifndef TESTMAIN
106	char	*name, *value;
107#endif
108	char	*namep, *valuep;
109	int	names, values, overwrite;
110
111#if FICL_ROBUST > 1
112	vmCheckStack(pVM, 5, 0);
113#endif
114	overwrite = stackPopINT(pVM->pStack);
115	names = stackPopINT(pVM->pStack);
116	namep = (char*) stackPopPtr(pVM->pStack);
117	values = stackPopINT(pVM->pStack);
118	valuep = (char*) stackPopPtr(pVM->pStack);
119
120#ifndef TESTMAIN
121	name = (char*) ficlMalloc(names+1);
122	if (!name)
123		vmThrowErr(pVM, "Error: out of memory");
124	strncpy(name, namep, names);
125	name[names] = '\0';
126	value = (char*) ficlMalloc(values+1);
127	if (!value)
128		vmThrowErr(pVM, "Error: out of memory");
129	strncpy(value, valuep, values);
130	value[values] = '\0';
131
132	setenv(name, value, overwrite);
133	ficlFree(name);
134	ficlFree(value);
135#endif
136
137	return;
138}
139
140void
141ficlGetenv(FICL_VM *pVM)
142{
143#ifndef TESTMAIN
144	char	*name, *value;
145#endif
146	char	*namep;
147	int	names;
148
149#if FICL_ROBUST > 1
150	vmCheckStack(pVM, 2, 2);
151#endif
152	names = stackPopINT(pVM->pStack);
153	namep = (char*) stackPopPtr(pVM->pStack);
154
155#ifndef TESTMAIN
156	name = (char*) ficlMalloc(names+1);
157	if (!name)
158		vmThrowErr(pVM, "Error: out of memory");
159	strncpy(name, namep, names);
160	name[names] = '\0';
161
162	value = getenv(name);
163	ficlFree(name);
164
165	if(value != NULL) {
166		stackPushPtr(pVM->pStack, value);
167		stackPushINT(pVM->pStack, strlen(value));
168	} else
169#endif
170		stackPushINT(pVM->pStack, -1);
171
172	return;
173}
174
175void
176ficlUnsetenv(FICL_VM *pVM)
177{
178#ifndef TESTMAIN
179	char	*name;
180#endif
181	char	*namep;
182	int	names;
183
184#if FICL_ROBUST > 1
185	vmCheckStack(pVM, 2, 0);
186#endif
187	names = stackPopINT(pVM->pStack);
188	namep = (char*) stackPopPtr(pVM->pStack);
189
190#ifndef TESTMAIN
191	name = (char*) ficlMalloc(names+1);
192	if (!name)
193		vmThrowErr(pVM, "Error: out of memory");
194	strncpy(name, namep, names);
195	name[names] = '\0';
196
197	unsetenv(name);
198	ficlFree(name);
199#endif
200
201	return;
202}
203
204void
205ficlCopyin(FICL_VM *pVM)
206{
207	void*		src;
208	vm_offset_t	dest;
209	size_t		len;
210
211#if FICL_ROBUST > 1
212	vmCheckStack(pVM, 3, 0);
213#endif
214
215	len = stackPopINT(pVM->pStack);
216	dest = stackPopINT(pVM->pStack);
217	src = stackPopPtr(pVM->pStack);
218
219#ifndef TESTMAIN
220	archsw.arch_copyin(src, dest, len);
221#endif
222
223	return;
224}
225
226void
227ficlCopyout(FICL_VM *pVM)
228{
229	void*		dest;
230	vm_offset_t	src;
231	size_t		len;
232
233#if FICL_ROBUST > 1
234	vmCheckStack(pVM, 3, 0);
235#endif
236
237	len = stackPopINT(pVM->pStack);
238	dest = stackPopPtr(pVM->pStack);
239	src = stackPopINT(pVM->pStack);
240
241#ifndef TESTMAIN
242	archsw.arch_copyout(src, dest, len);
243#endif
244
245	return;
246}
247
248void
249ficlFindfile(FICL_VM *pVM)
250{
251#ifndef TESTMAIN
252	char	*name, *type;
253#endif
254	char	*namep, *typep;
255	struct	preloaded_file* fp;
256	int	names, types;
257
258#if FICL_ROBUST > 1
259	vmCheckStack(pVM, 4, 1);
260#endif
261
262	types = stackPopINT(pVM->pStack);
263	typep = (char*) stackPopPtr(pVM->pStack);
264	names = stackPopINT(pVM->pStack);
265	namep = (char*) stackPopPtr(pVM->pStack);
266#ifndef TESTMAIN
267	name = (char*) ficlMalloc(names+1);
268	if (!name)
269		vmThrowErr(pVM, "Error: out of memory");
270	strncpy(name, namep, names);
271	name[names] = '\0';
272	type = (char*) ficlMalloc(types+1);
273	if (!type)
274		vmThrowErr(pVM, "Error: out of memory");
275	strncpy(type, typep, types);
276	type[types] = '\0';
277
278	fp = file_findfile(name, type);
279#else
280	fp = NULL;
281#endif
282	stackPushPtr(pVM->pStack, fp);
283
284	return;
285}
286
287#ifndef TESTMAIN
288#ifdef HAVE_PNP
289
290void
291ficlPnpdevices(FICL_VM *pVM)
292{
293	static int pnp_devices_initted = 0;
294#if FICL_ROBUST > 1
295	vmCheckStack(pVM, 0, 1);
296#endif
297
298	if(!pnp_devices_initted) {
299		STAILQ_INIT(&pnp_devices);
300		pnp_devices_initted = 1;
301	}
302
303	stackPushPtr(pVM->pStack, &pnp_devices);
304
305	return;
306}
307
308void
309ficlPnphandlers(FICL_VM *pVM)
310{
311#if FICL_ROBUST > 1
312	vmCheckStack(pVM, 0, 1);
313#endif
314
315	stackPushPtr(pVM->pStack, pnphandlers);
316
317	return;
318}
319
320#endif
321
322#endif /* ndef TESTMAIN */
323
324void
325ficlCcall(FICL_VM *pVM)
326{
327	int (*func)(int, ...);
328	int result, p[10];
329	int nparam, i;
330
331#if FICL_ROBUST > 1
332	vmCheckStack(pVM, 2, 0);
333#endif
334
335	func = stackPopPtr(pVM->pStack);
336	nparam = stackPopINT(pVM->pStack);
337
338#if FICL_ROBUST > 1
339	vmCheckStack(pVM, nparam, 1);
340#endif
341
342	for (i = 0; i < nparam; i++)
343		p[i] = stackPopINT(pVM->pStack);
344
345	result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8],
346	    p[9]);
347
348	stackPushINT(pVM->pStack, result);
349
350	return;
351}
352
353/**************************************************************************
354                        f i c l E x e c F D
355** reads in text from file fd and passes it to ficlExec()
356 * returns VM_OUTOFTEXT on success or the ficlExec() error code on
357 * failure.
358 */
359#define nLINEBUF 256
360int ficlExecFD(FICL_VM *pVM, int fd)
361{
362    char    cp[nLINEBUF];
363    int     nLine = 0, rval = VM_OUTOFTEXT;
364    char    ch;
365    CELL    id;
366
367    id = pVM->sourceID;
368    pVM->sourceID.i = fd;
369
370    /* feed each line to ficlExec */
371    while (1) {
372	int status, i;
373
374	i = 0;
375	while ((status = read(fd, &ch, 1)) > 0 && ch != '\n')
376	    cp[i++] = ch;
377        nLine++;
378	if (!i) {
379	    if (status < 1)
380		break;
381	    continue;
382	}
383        rval = ficlExecC(pVM, cp, i);
384	if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT)
385        {
386            pVM->sourceID = id;
387            return rval;
388        }
389    }
390    /*
391    ** Pass an empty line with SOURCE-ID == -1 to flush
392    ** any pending REFILLs (as required by FILE wordset)
393    */
394    pVM->sourceID.i = -1;
395    ficlExec(pVM, "");
396
397    pVM->sourceID = id;
398    return rval;
399}
400
401static void displayCellNoPad(FICL_VM *pVM)
402{
403    CELL c;
404#if FICL_ROBUST > 1
405    vmCheckStack(pVM, 1, 0);
406#endif
407    c = stackPop(pVM->pStack);
408    ltoa((c).i, pVM->pad, pVM->base);
409    vmTextOut(pVM, pVM->pad, 0);
410    return;
411}
412
413/*      isdir? - Return whether an fd corresponds to a directory.
414 *
415 * isdir? ( fd -- bool )
416 */
417static void isdirQuestion(FICL_VM *pVM)
418{
419    struct stat sb;
420    FICL_INT flag;
421    int fd;
422
423#if FICL_ROBUST > 1
424    vmCheckStack(pVM, 1, 1);
425#endif
426
427    fd = stackPopINT(pVM->pStack);
428    flag = FICL_FALSE;
429    do {
430        if (fd < 0)
431            break;
432        if (fstat(fd, &sb) < 0)
433            break;
434        if (!S_ISDIR(sb.st_mode))
435            break;
436        flag = FICL_TRUE;
437    } while (0);
438    stackPushINT(pVM->pStack, flag);
439}
440
441/*          fopen - open a file and return new fd on stack.
442 *
443 * fopen ( ptr count mode -- fd )
444 */
445static void pfopen(FICL_VM *pVM)
446{
447    int     mode, fd, count;
448    char    *ptr, *name;
449
450#if FICL_ROBUST > 1
451    vmCheckStack(pVM, 3, 1);
452#endif
453
454    mode = stackPopINT(pVM->pStack);    /* get mode */
455    count = stackPopINT(pVM->pStack);   /* get count */
456    ptr = stackPopPtr(pVM->pStack);     /* get ptr */
457
458    if ((count < 0) || (ptr == NULL)) {
459        stackPushINT(pVM->pStack, -1);
460        return;
461    }
462
463    /* ensure that the string is null terminated */
464    name = (char *)malloc(count+1);
465    bcopy(ptr,name,count);
466    name[count] = 0;
467
468    /* open the file */
469    fd = open(name, mode);
470    free(name);
471    stackPushINT(pVM->pStack, fd);
472    return;
473}
474
475/*          fclose - close a file who's fd is on stack.
476 *
477 * fclose ( fd -- )
478 */
479static void pfclose(FICL_VM *pVM)
480{
481    int fd;
482
483#if FICL_ROBUST > 1
484    vmCheckStack(pVM, 1, 0);
485#endif
486    fd = stackPopINT(pVM->pStack); /* get fd */
487    if (fd != -1)
488	close(fd);
489    return;
490}
491
492/*          fread - read file contents
493 *
494 * fread  ( fd buf nbytes  -- nread )
495 */
496static void pfread(FICL_VM *pVM)
497{
498    int     fd, len;
499    char *buf;
500
501#if FICL_ROBUST > 1
502    vmCheckStack(pVM, 3, 1);
503#endif
504    len = stackPopINT(pVM->pStack); /* get number of bytes to read */
505    buf = stackPopPtr(pVM->pStack); /* get buffer */
506    fd = stackPopINT(pVM->pStack); /* get fd */
507    if (len > 0 && buf && fd != -1)
508	stackPushINT(pVM->pStack, read(fd, buf, len));
509    else
510	stackPushINT(pVM->pStack, -1);
511    return;
512}
513
514/*      freaddir - read directory contents
515 *
516 * freaddir ( fd -- ptr len TRUE | FALSE )
517 */
518static void pfreaddir(FICL_VM *pVM)
519{
520#ifdef TESTMAIN
521    static struct dirent dirent;
522    struct stat sb;
523    char *buf;
524    off_t off, ptr;
525    u_int blksz;
526    int bufsz;
527#endif
528    struct dirent *d;
529    int fd;
530
531#if FICL_ROBUST > 1
532    vmCheckStack(pVM, 1, 3);
533#endif
534
535    fd = stackPopINT(pVM->pStack);
536#if TESTMAIN
537    /*
538     * The readdirfd() function is specific to the loader environment.
539     * We do the best we can to make freaddir work, but it's not at
540     * all guaranteed.
541     */
542    d = NULL;
543    buf = NULL;
544    do {
545	if (fd == -1)
546	    break;
547	if (fstat(fd, &sb) == -1)
548	    break;
549	blksz = (sb.st_blksize) ? sb.st_blksize : getpagesize();
550	if ((blksz & (blksz - 1)) != 0)
551	    break;
552	buf = malloc(blksz);
553	if (buf == NULL)
554	    break;
555	off = lseek(fd, 0LL, SEEK_CUR);
556	if (off == -1)
557	    break;
558	ptr = off;
559	if (lseek(fd, 0, SEEK_SET) == -1)
560	    break;
561	bufsz = getdents(fd, buf, blksz);
562	while (bufsz > 0 && bufsz <= ptr) {
563	    ptr -= bufsz;
564	    bufsz = getdents(fd, buf, blksz);
565	}
566	if (bufsz <= 0)
567	    break;
568	d = (void *)(buf + ptr);
569	dirent = *d;
570	off += d->d_reclen;
571	d = (lseek(fd, off, SEEK_SET) != off) ? NULL : &dirent;
572    } while (0);
573    if (buf != NULL)
574	free(buf);
575#else
576    d = readdirfd(fd);
577#endif
578    if (d != NULL) {
579        stackPushPtr(pVM->pStack, d->d_name);
580        stackPushINT(pVM->pStack, strlen(d->d_name));
581        stackPushINT(pVM->pStack, FICL_TRUE);
582    } else {
583        stackPushINT(pVM->pStack, FICL_FALSE);
584    }
585}
586
587/*          fload - interpret file contents
588 *
589 * fload  ( fd -- )
590 */
591static void pfload(FICL_VM *pVM)
592{
593    int     fd;
594
595#if FICL_ROBUST > 1
596    vmCheckStack(pVM, 1, 0);
597#endif
598    fd = stackPopINT(pVM->pStack); /* get fd */
599    if (fd != -1)
600	ficlExecFD(pVM, fd);
601    return;
602}
603
604/*          fwrite - write file contents
605 *
606 * fwrite  ( fd buf nbytes  -- nwritten )
607 */
608static void pfwrite(FICL_VM *pVM)
609{
610    int     fd, len;
611    char *buf;
612
613#if FICL_ROBUST > 1
614    vmCheckStack(pVM, 3, 1);
615#endif
616    len = stackPopINT(pVM->pStack); /* get number of bytes to read */
617    buf = stackPopPtr(pVM->pStack); /* get buffer */
618    fd = stackPopINT(pVM->pStack); /* get fd */
619    if (len > 0 && buf && fd != -1)
620	stackPushINT(pVM->pStack, write(fd, buf, len));
621    else
622	stackPushINT(pVM->pStack, -1);
623    return;
624}
625
626/*          fseek - seek to a new position in a file
627 *
628 * fseek  ( fd ofs whence  -- pos )
629 */
630static void pfseek(FICL_VM *pVM)
631{
632    int     fd, pos, whence;
633
634#if FICL_ROBUST > 1
635    vmCheckStack(pVM, 3, 1);
636#endif
637    whence = stackPopINT(pVM->pStack);
638    pos = stackPopINT(pVM->pStack);
639    fd = stackPopINT(pVM->pStack);
640    stackPushINT(pVM->pStack, lseek(fd, pos, whence));
641    return;
642}
643
644/*           key - get a character from stdin
645 *
646 * key ( -- char )
647 */
648static void key(FICL_VM *pVM)
649{
650#if FICL_ROBUST > 1
651    vmCheckStack(pVM, 0, 1);
652#endif
653    stackPushINT(pVM->pStack, getchar());
654    return;
655}
656
657/*           key? - check for a character from stdin (FACILITY)
658 *
659 * key? ( -- flag )
660 */
661static void keyQuestion(FICL_VM *pVM)
662{
663#if FICL_ROBUST > 1
664    vmCheckStack(pVM, 0, 1);
665#endif
666#ifdef TESTMAIN
667    /* XXX Since we don't fiddle with termios, let it always succeed... */
668    stackPushINT(pVM->pStack, FICL_TRUE);
669#else
670    /* But here do the right thing. */
671    stackPushINT(pVM->pStack, ischar()? FICL_TRUE : FICL_FALSE);
672#endif
673    return;
674}
675
676/* seconds - gives number of seconds since beginning of time
677 *
678 * beginning of time is defined as:
679 *
680 *	BTX	- number of seconds since midnight
681 *	FreeBSD	- number of seconds since Jan 1 1970
682 *
683 * seconds ( -- u )
684 */
685static void pseconds(FICL_VM *pVM)
686{
687#if FICL_ROBUST > 1
688    vmCheckStack(pVM,0,1);
689#endif
690    stackPushUNS(pVM->pStack, (FICL_UNS) time(NULL));
691    return;
692}
693
694/* ms - wait at least that many milliseconds (FACILITY)
695 *
696 * ms ( u -- )
697 *
698 */
699static void ms(FICL_VM *pVM)
700{
701#if FICL_ROBUST > 1
702    vmCheckStack(pVM,1,0);
703#endif
704#ifdef TESTMAIN
705    usleep(stackPopUNS(pVM->pStack)*1000);
706#else
707    delay(stackPopUNS(pVM->pStack)*1000);
708#endif
709    return;
710}
711
712/*           fkey - get a character from a file
713 *
714 * fkey ( file -- char )
715 */
716static void fkey(FICL_VM *pVM)
717{
718    int i, fd;
719    char ch;
720
721#if FICL_ROBUST > 1
722    vmCheckStack(pVM, 1, 1);
723#endif
724    fd = stackPopINT(pVM->pStack);
725    i = read(fd, &ch, 1);
726    stackPushINT(pVM->pStack, i > 0 ? ch : -1);
727    return;
728}
729
730/*
731** Retrieves free space remaining on the dictionary
732*/
733
734static void freeHeap(FICL_VM *pVM)
735{
736    stackPushINT(pVM->pStack, dictCellsAvail(ficlGetDict(pVM->pSys)));
737}
738
739
740/******************* Increase dictionary size on-demand ******************/
741
742static void ficlDictThreshold(FICL_VM *pVM)
743{
744    stackPushPtr(pVM->pStack, &dictThreshold);
745}
746
747static void ficlDictIncrease(FICL_VM *pVM)
748{
749    stackPushPtr(pVM->pStack, &dictIncrease);
750}
751
752
753/**************************************************************************
754                        f i c l C o m p i l e P l a t f o r m
755** Build FreeBSD platform extensions into the system dictionary
756**************************************************************************/
757void ficlCompilePlatform(FICL_SYSTEM *pSys)
758{
759    FICL_DICT *dp = pSys->dp;
760    assert (dp);
761
762    dictAppendWord(dp, ".#",        displayCellNoPad,    FW_DEFAULT);
763    dictAppendWord(dp, "isdir?",    isdirQuestion,  FW_DEFAULT);
764    dictAppendWord(dp, "fopen",	    pfopen,	    FW_DEFAULT);
765    dictAppendWord(dp, "fclose",    pfclose,	    FW_DEFAULT);
766    dictAppendWord(dp, "fread",	    pfread,	    FW_DEFAULT);
767    dictAppendWord(dp, "freaddir",  pfreaddir,	    FW_DEFAULT);
768    dictAppendWord(dp, "fload",	    pfload,	    FW_DEFAULT);
769    dictAppendWord(dp, "fkey",	    fkey,	    FW_DEFAULT);
770    dictAppendWord(dp, "fseek",     pfseek,	    FW_DEFAULT);
771    dictAppendWord(dp, "fwrite",    pfwrite,	    FW_DEFAULT);
772    dictAppendWord(dp, "key",	    key,	    FW_DEFAULT);
773    dictAppendWord(dp, "key?",	    keyQuestion,    FW_DEFAULT);
774    dictAppendWord(dp, "ms",        ms,             FW_DEFAULT);
775    dictAppendWord(dp, "seconds",   pseconds,       FW_DEFAULT);
776    dictAppendWord(dp, "heap?",     freeHeap,       FW_DEFAULT);
777    dictAppendWord(dp, "dictthreshold", ficlDictThreshold, FW_DEFAULT);
778    dictAppendWord(dp, "dictincrease", ficlDictIncrease, FW_DEFAULT);
779
780    dictAppendWord(dp, "setenv",    ficlSetenv,	    FW_DEFAULT);
781    dictAppendWord(dp, "setenv?",   ficlSetenvq,    FW_DEFAULT);
782    dictAppendWord(dp, "getenv",    ficlGetenv,	    FW_DEFAULT);
783    dictAppendWord(dp, "unsetenv",  ficlUnsetenv,   FW_DEFAULT);
784    dictAppendWord(dp, "copyin",    ficlCopyin,	    FW_DEFAULT);
785    dictAppendWord(dp, "copyout",   ficlCopyout,    FW_DEFAULT);
786    dictAppendWord(dp, "findfile",  ficlFindfile,   FW_DEFAULT);
787    dictAppendWord(dp, "ccall",	    ficlCcall,	    FW_DEFAULT);
788#ifndef TESTMAIN
789#ifdef __i386__
790    dictAppendWord(dp, "outb",      ficlOutb,       FW_DEFAULT);
791    dictAppendWord(dp, "inb",       ficlInb,        FW_DEFAULT);
792#endif
793#ifdef HAVE_PNP
794    dictAppendWord(dp, "pnpdevices",ficlPnpdevices, FW_DEFAULT);
795    dictAppendWord(dp, "pnphandlers",ficlPnphandlers, FW_DEFAULT);
796#endif
797#endif
798
799#if defined(PC98)
800    ficlSetEnv(pSys, "arch-pc98",         FICL_TRUE);
801#elif defined(__i386__)
802    ficlSetEnv(pSys, "arch-i386",         FICL_TRUE);
803    ficlSetEnv(pSys, "arch-ia64",         FICL_FALSE);
804    ficlSetEnv(pSys, "arch-powerpc",      FICL_FALSE);
805#elif defined(__ia64__)
806    ficlSetEnv(pSys, "arch-i386",         FICL_FALSE);
807    ficlSetEnv(pSys, "arch-ia64",         FICL_TRUE);
808    ficlSetEnv(pSys, "arch-powerpc",      FICL_FALSE);
809#elif defined(__powerpc__)
810    ficlSetEnv(pSys, "arch-i386",         FICL_FALSE);
811    ficlSetEnv(pSys, "arch-ia64",         FICL_FALSE);
812    ficlSetEnv(pSys, "arch-powerpc",      FICL_TRUE);
813#endif
814
815    return;
816}
817
818