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$ 27 */ 28 29 /* 30 * l o a d e r . c 31 * Additional FICL words designed for FreeBSD's loader 32 */ 33 34 #ifndef _STANDALONE 35 #include <sys/types.h> 36 #include <sys/stat.h> 37 #include <dirent.h> 38 #include <fcntl.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <unistd.h> 42 #include <strings.h> 43 #include <termios.h> 44 #else 45 #include <stand.h> 46 #ifdef __i386__ 47 #include <machine/cpufunc.h> 48 #endif 49 #include "bootstrap.h" 50 #endif 51 #ifdef _STANDALONE 52 #include <uuid.h> 53 #else 54 #include <uuid/uuid.h> 55 #endif 56 #include <string.h> 57 #include "ficl.h" 58 59 /* 60 * FreeBSD's loader interaction words and extras 61 * 62 * setenv ( value n name n' -- ) 63 * setenv? ( value n name n' flag -- ) 64 * getenv ( addr n -- addr' n' | -1 ) 65 * unsetenv ( addr n -- ) 66 * copyin ( addr addr' len -- ) 67 * copyout ( addr addr' len -- ) 68 * findfile ( name len type len' -- addr ) 69 * ccall ( [[...[p10] p9] ... p1] n addr -- result ) 70 * uuid-from-string ( addr n -- addr' ) 71 * uuid-to-string ( addr' -- addr n | -1 ) 72 * .# ( value -- ) 73 */ 74 75 void 76 ficlSetenv(ficlVm *pVM) 77 { 78 char *name, *value; 79 char *namep, *valuep; 80 int names, values; 81 82 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 4, 0); 83 84 names = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 85 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM)); 86 values = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 87 valuep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM)); 88 89 name = (char *)ficlMalloc(names+1); 90 if (!name) 91 ficlVmThrowError(pVM, "Error: out of memory"); 92 strncpy(name, namep, names); 93 name[names] = '\0'; 94 value = (char *)ficlMalloc(values+1); 95 if (!value) 96 ficlVmThrowError(pVM, "Error: out of memory"); 97 strncpy(value, valuep, values); 98 value[values] = '\0'; 99 100 setenv(name, value, 1); 101 ficlFree(name); 102 ficlFree(value); 103 } 104 105 void 106 ficlSetenvq(ficlVm *pVM) 107 { 108 char *name, *value; 109 char *namep, *valuep; 110 int names, values, overwrite; 111 112 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 5, 0); 113 114 overwrite = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 115 names = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 116 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM)); 117 values = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 118 valuep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM)); 119 120 name = (char *)ficlMalloc(names+1); 121 if (!name) 122 ficlVmThrowError(pVM, "Error: out of memory"); 123 strncpy(name, namep, names); 124 name[names] = '\0'; 125 value = (char *)ficlMalloc(values+1); 126 if (!value) 127 ficlVmThrowError(pVM, "Error: out of memory"); 128 strncpy(value, valuep, values); 129 value[values] = '\0'; 130 131 setenv(name, value, overwrite); 132 ficlFree(name); 133 ficlFree(value); 134 } 135 136 void 137 ficlGetenv(ficlVm *pVM) 138 { 139 char *name, *value; 140 char *namep; 141 int names; 142 143 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 2); 144 145 names = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 146 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM)); 147 148 name = (char *)ficlMalloc(names+1); 149 if (!name) 150 ficlVmThrowError(pVM, "Error: out of memory"); 151 strncpy(name, namep, names); 152 name[names] = '\0'; 153 154 value = getenv(name); 155 ficlFree(name); 156 157 if (value != NULL) { 158 ficlStackPushPointer(ficlVmGetDataStack(pVM), value); 159 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(value)); 160 } else 161 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1); 162 } 163 164 void 165 ficlUnsetenv(ficlVm *pVM) 166 { 167 char *name; 168 char *namep; 169 int names; 170 171 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0); 172 173 names = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 174 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM)); 175 176 name = (char *)ficlMalloc(names+1); 177 if (!name) 178 ficlVmThrowError(pVM, "Error: out of memory"); 179 strncpy(name, namep, names); 180 name[names] = '\0'; 181 182 unsetenv(name); 183 ficlFree(name); 184 } 185 186 void 187 ficlCopyin(ficlVm *pVM) 188 { 189 #ifdef _STANDALONE 190 void* src; 191 vm_offset_t dest; 192 size_t len; 193 #endif 194 195 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 0); 196 197 #ifdef _STANDALONE 198 len = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 199 dest = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 200 src = ficlStackPopPointer(ficlVmGetDataStack(pVM)); 201 archsw.arch_copyin(src, dest, len); 202 #else 203 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM)); 204 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM)); 205 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM)); 206 #endif 207 } 208 209 void 210 ficlCopyout(ficlVm *pVM) 211 { 212 #ifdef _STANDALONE 213 void* dest; 214 vm_offset_t src; 215 size_t len; 216 #endif 217 218 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 0); 219 220 #ifdef _STANDALONE 221 len = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 222 dest = ficlStackPopPointer(ficlVmGetDataStack(pVM)); 223 src = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 224 archsw.arch_copyout(src, dest, len); 225 #else 226 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM)); 227 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM)); 228 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM)); 229 #endif 230 } 231 232 void 233 ficlFindfile(ficlVm *pVM) 234 { 235 #ifdef _STANDALONE 236 char *name, *type; 237 char *namep, *typep; 238 int names, types; 239 #endif 240 struct preloaded_file *fp; 241 242 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 4, 1); 243 244 #ifdef _STANDALONE 245 types = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 246 typep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM)); 247 names = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 248 namep = (char *)ficlStackPopPointer(ficlVmGetDataStack(pVM)); 249 250 name = (char *)ficlMalloc(names+1); 251 if (!name) 252 ficlVmThrowError(pVM, "Error: out of memory"); 253 strncpy(name, namep, names); 254 name[names] = '\0'; 255 type = (char *)ficlMalloc(types+1); 256 if (!type) 257 ficlVmThrowError(pVM, "Error: out of memory"); 258 strncpy(type, typep, types); 259 type[types] = '\0'; 260 261 fp = file_findfile(name, type); 262 #else 263 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM)); 264 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM)); 265 (void) ficlStackPopInteger(ficlVmGetDataStack(pVM)); 266 (void) ficlStackPopPointer(ficlVmGetDataStack(pVM)); 267 268 fp = NULL; 269 #endif 270 ficlStackPushPointer(ficlVmGetDataStack(pVM), fp); 271 } 272 273 void 274 ficlCcall(ficlVm *pVM) 275 { 276 int (*func)(int, ...); 277 int result, p[10]; 278 int nparam, i; 279 280 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0); 281 282 func = (int (*)(int, ...))ficlStackPopPointer(ficlVmGetDataStack(pVM)); 283 nparam = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 284 285 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), nparam, 1); 286 287 for (i = 0; i < nparam; i++) 288 p[i] = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 289 290 result = func(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], 291 p[9]); 292 293 ficlStackPushInteger(ficlVmGetDataStack(pVM), result); 294 } 295 296 void 297 ficlUuidFromString(ficlVm *pVM) 298 { 299 char *uuid; 300 char *uuid_ptr; 301 int uuid_size; 302 uuid_t *u; 303 #ifdef _STANDALONE 304 uint32_t status; 305 #else 306 int status; 307 #endif 308 309 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 0); 310 311 uuid_size = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 312 uuid_ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM)); 313 314 uuid = ficlMalloc(uuid_size + 1); 315 if (!uuid) 316 ficlVmThrowError(pVM, "Error: out of memory"); 317 (void) memcpy(uuid, uuid_ptr, uuid_size); 318 uuid[uuid_size] = '\0'; 319 320 u = ficlMalloc(sizeof (*u)); 321 #ifdef _STANDALONE 322 uuid_from_string(uuid, u, &status); 323 ficlFree(uuid); 324 if (status != uuid_s_ok) { 325 ficlFree(u); 326 u = NULL; 327 } 328 #else 329 status = uuid_parse(uuid, *u); 330 ficlFree(uuid); 331 if (status != 0) { 332 ficlFree(u); 333 u = NULL; 334 } 335 #endif 336 ficlStackPushPointer(ficlVmGetDataStack(pVM), u); 337 } 338 339 void 340 ficlUuidToString(ficlVm *pVM) 341 { 342 char *uuid; 343 uuid_t *u; 344 #ifdef _STANDALONE 345 uint32_t status; 346 #endif 347 348 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0); 349 350 u = ficlStackPopPointer(ficlVmGetDataStack(pVM)); 351 #ifdef _STANDALONE 352 uuid_to_string(u, &uuid, &status); 353 if (status == uuid_s_ok) { 354 ficlStackPushPointer(ficlVmGetDataStack(pVM), uuid); 355 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(uuid)); 356 } else 357 #else 358 uuid = ficlMalloc(UUID_PRINTABLE_STRING_LENGTH); 359 if (uuid != NULL) { 360 uuid_unparse(*u, uuid); 361 ficlStackPushPointer(ficlVmGetDataStack(pVM), uuid); 362 ficlStackPushInteger(ficlVmGetDataStack(pVM), strlen(uuid)); 363 } else 364 #endif 365 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1); 366 } 367 368 /* 369 * f i c l E x e c F D 370 * reads in text from file fd and passes it to ficlExec() 371 * returns FICL_VM_STATUS_OUT_OF_TEXT on success or the ficlExec() error 372 * code on failure. 373 */ 374 #define nLINEBUF 256 375 int 376 ficlExecFD(ficlVm *pVM, int fd) 377 { 378 char cp[nLINEBUF]; 379 int nLine = 0, rval = FICL_VM_STATUS_OUT_OF_TEXT; 380 char ch; 381 ficlCell id; 382 ficlString s; 383 384 id = pVM->sourceId; 385 pVM->sourceId.i = fd+1; /* in loader we can get 0, there is no stdin */ 386 387 /* feed each line to ficlExec */ 388 while (1) { 389 int status, i; 390 391 i = 0; 392 while ((status = read(fd, &ch, 1)) > 0 && ch != '\n') 393 cp[i++] = ch; 394 nLine++; 395 if (!i) { 396 if (status < 1) 397 break; 398 continue; 399 } 400 if (cp[i] == '\n') 401 cp[i] = '\0'; 402 403 FICL_STRING_SET_POINTER(s, cp); 404 FICL_STRING_SET_LENGTH(s, i); 405 406 rval = ficlVmExecuteString(pVM, s); 407 if (rval != FICL_VM_STATUS_QUIT && 408 rval != FICL_VM_STATUS_USER_EXIT && 409 rval != FICL_VM_STATUS_OUT_OF_TEXT) { 410 pVM->sourceId = id; 411 (void) ficlVmEvaluate(pVM, ""); 412 return (rval); 413 } 414 } 415 pVM->sourceId = id; 416 417 /* 418 * Pass an empty line with SOURCE-ID == -1 to flush 419 * any pending REFILLs (as required by FILE wordset) 420 */ 421 (void) ficlVmEvaluate(pVM, ""); 422 423 if (rval == FICL_VM_STATUS_USER_EXIT) 424 ficlVmThrow(pVM, FICL_VM_STATUS_USER_EXIT); 425 426 return (rval); 427 } 428 429 static void displayCellNoPad(ficlVm *pVM) 430 { 431 ficlCell c; 432 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0); 433 434 c = ficlStackPop(ficlVmGetDataStack(pVM)); 435 ficlLtoa((c).i, pVM->pad, pVM->base); 436 ficlVmTextOut(pVM, pVM->pad); 437 } 438 439 /* 440 * isdir? - Return whether an fd corresponds to a directory. 441 * 442 * isdir? ( fd -- bool ) 443 */ 444 static void 445 isdirQuestion(ficlVm *pVM) 446 { 447 struct stat sb; 448 ficlInteger flag; 449 int fd; 450 451 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 1); 452 453 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 454 flag = FICL_FALSE; 455 do { 456 if (fd < 0) 457 break; 458 if (fstat(fd, &sb) < 0) 459 break; 460 if (!S_ISDIR(sb.st_mode)) 461 break; 462 flag = FICL_TRUE; 463 } while (0); 464 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag); 465 } 466 467 /* 468 * fopen - open a file and return new fd on stack. 469 * 470 * fopen ( ptr count mode -- fd ) 471 */ 472 extern char *get_dev(const char *); 473 474 static void 475 pfopen(ficlVm *pVM) 476 { 477 int mode, fd, count; 478 char *ptr, *name; 479 #ifndef _STANDALONE 480 char *tmp; 481 #endif 482 483 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1); 484 485 mode = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get mode */ 486 count = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get count */ 487 ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get ptr */ 488 489 if ((count < 0) || (ptr == NULL)) { 490 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1); 491 return; 492 } 493 494 /* ensure that the string is null terminated */ 495 name = (char *)malloc(count+1); 496 bcopy(ptr, name, count); 497 name[count] = 0; 498 #ifndef _STANDALONE 499 tmp = get_dev(name); 500 free(name); 501 name = tmp; 502 #endif 503 504 /* open the file */ 505 fd = open(name, mode); 506 free(name); 507 ficlStackPushInteger(ficlVmGetDataStack(pVM), fd); 508 } 509 510 /* 511 * fclose - close a file who's fd is on stack. 512 * fclose ( fd -- ) 513 */ 514 static void 515 pfclose(ficlVm *pVM) 516 { 517 int fd; 518 519 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0); 520 521 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */ 522 if (fd != -1) 523 close(fd); 524 } 525 526 /* 527 * fread - read file contents 528 * fread ( fd buf nbytes -- nread ) 529 */ 530 static void 531 pfread(ficlVm *pVM) 532 { 533 int fd, len; 534 char *buf; 535 536 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1); 537 538 len = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 539 buf = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get buffer */ 540 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */ 541 if (len > 0 && buf && fd != -1) 542 ficlStackPushInteger(ficlVmGetDataStack(pVM), 543 read(fd, buf, len)); 544 else 545 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1); 546 } 547 548 /* 549 * fopendir - open directory 550 * 551 * fopendir ( addr len -- ptr TRUE | FALSE ) 552 */ 553 static void pfopendir(ficlVm *pVM) 554 { 555 #ifndef _STANDALONE 556 DIR *dir; 557 char *tmp; 558 #else 559 struct stat sb; 560 int fd; 561 #endif 562 int count; 563 char *ptr, *name; 564 ficlInteger flag = FICL_FALSE; 565 566 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 2, 1); 567 568 count = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 569 ptr = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get ptr */ 570 571 if ((count < 0) || (ptr == NULL)) { 572 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1); 573 return; 574 } 575 /* ensure that the string is null terminated */ 576 name = (char *)malloc(count+1); 577 bcopy(ptr, name, count); 578 name[count] = 0; 579 #ifndef _STANDALONE 580 tmp = get_dev(name); 581 free(name); 582 name = tmp; 583 #else 584 fd = open(name, O_RDONLY); 585 free(name); 586 do { 587 if (fd < 0) 588 break; 589 if (fstat(fd, &sb) < 0) 590 break; 591 if (!S_ISDIR(sb.st_mode)) 592 break; 593 flag = FICL_TRUE; 594 ficlStackPushInteger(ficlVmGetDataStack(pVM), fd); 595 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag); 596 return; 597 } while (0); 598 599 if (fd >= 0) 600 close(fd); 601 602 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag); 603 return; 604 #endif 605 #ifndef _STANDALONE 606 dir = opendir(name); 607 if (dir == NULL) { 608 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag); 609 return; 610 } else 611 flag = FICL_TRUE; 612 613 ficlStackPushPointer(ficlVmGetDataStack(pVM), dir); 614 ficlStackPushInteger(ficlVmGetDataStack(pVM), flag); 615 #endif 616 } 617 618 /* 619 * freaddir - read directory contents 620 * freaddir ( fd -- ptr len TRUE | FALSE ) 621 */ 622 static void 623 pfreaddir(ficlVm *pVM) 624 { 625 #ifndef _STANDALONE 626 static DIR *dir = NULL; 627 #else 628 int fd; 629 #endif 630 struct dirent *d = NULL; 631 632 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 3); 633 /* 634 * libstand readdir does not always return . nor .. so filter 635 * them out to have consistent behaviour. 636 */ 637 #ifndef _STANDALONE 638 dir = ficlStackPopPointer(ficlVmGetDataStack(pVM)); 639 if (dir != NULL) 640 do { 641 d = readdir(dir); 642 if (d != NULL && strcmp(d->d_name, ".") == 0) 643 continue; 644 if (d != NULL && strcmp(d->d_name, "..") == 0) 645 continue; 646 break; 647 } while (d != NULL); 648 #else 649 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 650 if (fd != -1) 651 do { 652 d = readdirfd(fd); 653 if (d != NULL && strcmp(d->d_name, ".") == 0) 654 continue; 655 if (d != NULL && strcmp(d->d_name, "..") == 0) 656 continue; 657 break; 658 } while (d != NULL); 659 #endif 660 if (d != NULL) { 661 ficlStackPushPointer(ficlVmGetDataStack(pVM), d->d_name); 662 ficlStackPushInteger(ficlVmGetDataStack(pVM), 663 strlen(d->d_name)); 664 ficlStackPushInteger(ficlVmGetDataStack(pVM), FICL_TRUE); 665 } else { 666 ficlStackPushInteger(ficlVmGetDataStack(pVM), FICL_FALSE); 667 } 668 } 669 670 /* 671 * fclosedir - close a dir on stack. 672 * 673 * fclosedir ( fd -- ) 674 */ 675 static void 676 pfclosedir(ficlVm *pVM) 677 { 678 #ifndef _STANDALONE 679 DIR *dir; 680 #else 681 int fd; 682 #endif 683 684 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0); 685 686 #ifndef _STANDALONE 687 dir = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get dir */ 688 if (dir != NULL) 689 closedir(dir); 690 #else 691 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */ 692 if (fd != -1) 693 close(fd); 694 #endif 695 } 696 697 /* 698 * fload - interpret file contents 699 * 700 * fload ( fd -- ) 701 */ 702 static void pfload(ficlVm *pVM) 703 { 704 int fd; 705 706 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0); 707 708 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */ 709 if (fd != -1) 710 ficlExecFD(pVM, fd); 711 } 712 713 /* 714 * fwrite - write file contents 715 * 716 * fwrite ( fd buf nbytes -- nwritten ) 717 */ 718 static void 719 pfwrite(ficlVm *pVM) 720 { 721 int fd, len; 722 char *buf; 723 724 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1); 725 726 len = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* bytes to read */ 727 buf = ficlStackPopPointer(ficlVmGetDataStack(pVM)); /* get buffer */ 728 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); /* get fd */ 729 if (len > 0 && buf && fd != -1) 730 ficlStackPushInteger(ficlVmGetDataStack(pVM), 731 write(fd, buf, len)); 732 else 733 ficlStackPushInteger(ficlVmGetDataStack(pVM), -1); 734 } 735 736 /* 737 * fseek - seek to a new position in a file 738 * 739 * fseek ( fd ofs whence -- pos ) 740 */ 741 static void 742 pfseek(ficlVm *pVM) 743 { 744 int fd, pos, whence; 745 746 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 3, 1); 747 748 whence = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 749 pos = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 750 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 751 ficlStackPushInteger(ficlVmGetDataStack(pVM), lseek(fd, pos, whence)); 752 } 753 754 /* 755 * key - get a character from stdin 756 * 757 * key ( -- char ) 758 */ 759 static void 760 key(ficlVm *pVM) 761 { 762 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1); 763 764 ficlStackPushInteger(ficlVmGetDataStack(pVM), getchar()); 765 } 766 767 /* 768 * key? - check for a character from stdin (FACILITY) 769 * key? ( -- flag ) 770 */ 771 static void 772 keyQuestion(ficlVm *pVM) 773 { 774 #ifndef _STANDALONE 775 char ch = -1; 776 struct termios oldt; 777 struct termios newt; 778 #endif 779 780 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1); 781 782 #ifndef _STANDALONE 783 tcgetattr(STDIN_FILENO, &oldt); 784 newt = oldt; 785 newt.c_lflag &= ~(ICANON | ECHO); 786 newt.c_cc[VMIN] = 0; 787 newt.c_cc[VTIME] = 0; 788 tcsetattr(STDIN_FILENO, TCSANOW, &newt); 789 ch = getchar(); 790 tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 791 792 if (ch != -1) 793 (void) ungetc(ch, stdin); 794 795 ficlStackPushInteger(ficlVmGetDataStack(pVM), 796 ch != -1? FICL_TRUE : FICL_FALSE); 797 #else 798 ficlStackPushInteger(ficlVmGetDataStack(pVM), 799 ischar()? FICL_TRUE : FICL_FALSE); 800 #endif 801 } 802 803 /* 804 * seconds - gives number of seconds since beginning of time 805 * 806 * beginning of time is defined as: 807 * 808 * BTX - number of seconds since midnight 809 * FreeBSD - number of seconds since Jan 1 1970 810 * 811 * seconds ( -- u ) 812 */ 813 static void 814 pseconds(ficlVm *pVM) 815 { 816 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 0, 1); 817 818 ficlStackPushUnsigned(ficlVmGetDataStack(pVM), 819 (ficlUnsigned) time(NULL)); 820 } 821 822 /* 823 * ms - wait at least that many milliseconds (FACILITY) 824 * ms ( u -- ) 825 */ 826 static void 827 ms(ficlVm *pVM) 828 { 829 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 0); 830 831 #ifndef _STANDALONE 832 usleep(ficlStackPopUnsigned(ficlVmGetDataStack(pVM)) * 1000); 833 #else 834 delay(ficlStackPopUnsigned(ficlVmGetDataStack(pVM)) * 1000); 835 #endif 836 } 837 838 /* 839 * fkey - get a character from a file 840 * fkey ( file -- char ) 841 */ 842 static void 843 fkey(ficlVm *pVM) 844 { 845 int i, fd; 846 char ch; 847 848 FICL_STACK_CHECK(ficlVmGetDataStack(pVM), 1, 1); 849 850 fd = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 851 i = read(fd, &ch, 1); 852 ficlStackPushInteger(ficlVmGetDataStack(pVM), i > 0 ? ch : -1); 853 } 854 855 856 #ifdef _STANDALONE 857 #ifdef __i386__ 858 859 /* 860 * outb ( port# c -- ) 861 * Store a byte to I/O port number port# 862 */ 863 void 864 ficlOutb(ficlVm *pVM) 865 { 866 uint8_t c; 867 uint32_t port; 868 869 port = ficlStackPopUnsigned(ficlVmGetDataStack(pVM)); 870 c = ficlStackPopInteger(ficlVmGetDataStack(pVM)); 871 outb(port, c); 872 } 873 874 /* 875 * inb ( port# -- c ) 876 * Fetch a byte from I/O port number port# 877 */ 878 void 879 ficlInb(ficlVm *pVM) 880 { 881 uint8_t c; 882 uint32_t port; 883 884 port = ficlStackPopUnsigned(ficlVmGetDataStack(pVM)); 885 c = inb(port); 886 ficlStackPushInteger(ficlVmGetDataStack(pVM), c); 887 } 888 #endif 889 #endif 890 891 /* 892 * Retrieves free space remaining on the dictionary 893 */ 894 static void 895 freeHeap(ficlVm *pVM) 896 { 897 ficlStackPushInteger(ficlVmGetDataStack(pVM), 898 ficlDictionaryCellsAvailable(ficlVmGetDictionary(pVM))); 899 } 900 901 /* 902 * f i c l C o m p i l e P l a t f o r m 903 * Build FreeBSD platform extensions into the system dictionary 904 */ 905 void 906 ficlSystemCompilePlatform(ficlSystem *pSys) 907 { 908 ficlDictionary *dp = ficlSystemGetDictionary(pSys); 909 ficlDictionary *env = ficlSystemGetEnvironment(pSys); 910 #ifdef _STANDALONE 911 ficlCompileFcn **fnpp; 912 #endif 913 914 FICL_SYSTEM_ASSERT(pSys, dp); 915 FICL_SYSTEM_ASSERT(pSys, env); 916 917 ficlDictionarySetPrimitive(dp, ".#", displayCellNoPad, 918 FICL_WORD_DEFAULT); 919 ficlDictionarySetPrimitive(dp, "isdir?", isdirQuestion, 920 FICL_WORD_DEFAULT); 921 ficlDictionarySetPrimitive(dp, "fopen", pfopen, FICL_WORD_DEFAULT); 922 ficlDictionarySetPrimitive(dp, "fclose", pfclose, FICL_WORD_DEFAULT); 923 ficlDictionarySetPrimitive(dp, "fread", pfread, FICL_WORD_DEFAULT); 924 ficlDictionarySetPrimitive(dp, "fopendir", pfopendir, 925 FICL_WORD_DEFAULT); 926 ficlDictionarySetPrimitive(dp, "freaddir", pfreaddir, 927 FICL_WORD_DEFAULT); 928 ficlDictionarySetPrimitive(dp, "fclosedir", pfclosedir, 929 FICL_WORD_DEFAULT); 930 ficlDictionarySetPrimitive(dp, "fload", pfload, FICL_WORD_DEFAULT); 931 ficlDictionarySetPrimitive(dp, "fkey", fkey, FICL_WORD_DEFAULT); 932 ficlDictionarySetPrimitive(dp, "fseek", pfseek, FICL_WORD_DEFAULT); 933 ficlDictionarySetPrimitive(dp, "fwrite", pfwrite, FICL_WORD_DEFAULT); 934 ficlDictionarySetPrimitive(dp, "key", key, FICL_WORD_DEFAULT); 935 ficlDictionarySetPrimitive(dp, "key?", keyQuestion, FICL_WORD_DEFAULT); 936 ficlDictionarySetPrimitive(dp, "ms", ms, FICL_WORD_DEFAULT); 937 ficlDictionarySetPrimitive(dp, "seconds", pseconds, FICL_WORD_DEFAULT); 938 ficlDictionarySetPrimitive(dp, "heap?", freeHeap, FICL_WORD_DEFAULT); 939 940 ficlDictionarySetPrimitive(dp, "setenv", ficlSetenv, FICL_WORD_DEFAULT); 941 ficlDictionarySetPrimitive(dp, "setenv?", ficlSetenvq, 942 FICL_WORD_DEFAULT); 943 ficlDictionarySetPrimitive(dp, "getenv", ficlGetenv, FICL_WORD_DEFAULT); 944 ficlDictionarySetPrimitive(dp, "unsetenv", ficlUnsetenv, 945 FICL_WORD_DEFAULT); 946 ficlDictionarySetPrimitive(dp, "copyin", ficlCopyin, FICL_WORD_DEFAULT); 947 ficlDictionarySetPrimitive(dp, "copyout", ficlCopyout, 948 FICL_WORD_DEFAULT); 949 ficlDictionarySetPrimitive(dp, "findfile", ficlFindfile, 950 FICL_WORD_DEFAULT); 951 ficlDictionarySetPrimitive(dp, "ccall", ficlCcall, FICL_WORD_DEFAULT); 952 ficlDictionarySetPrimitive(dp, "uuid-from-string", ficlUuidFromString, 953 FICL_WORD_DEFAULT); 954 ficlDictionarySetPrimitive(dp, "uuid-to-string", ficlUuidToString, 955 FICL_WORD_DEFAULT); 956 #ifdef _STANDALONE 957 #ifdef __i386__ 958 ficlDictionarySetPrimitive(dp, "outb", ficlOutb, FICL_WORD_DEFAULT); 959 ficlDictionarySetPrimitive(dp, "inb", ficlInb, FICL_WORD_DEFAULT); 960 #endif 961 /* Register words from linker set. */ 962 SET_FOREACH(fnpp, Xficl_compile_set) 963 (*fnpp)(pSys); 964 #endif 965 966 #if defined(__i386__) || defined(__amd64__) 967 ficlDictionarySetConstant(env, "arch-i386", FICL_TRUE); 968 ficlDictionarySetConstant(env, "arch-sparc", FICL_FALSE); 969 #endif 970 #ifdef __sparc 971 ficlDictionarySetConstant(env, "arch-i386", FICL_FALSE); 972 ficlDictionarySetConstant(env, "arch-sparc", FICL_TRUE); 973 #endif 974 } 975