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