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