1.\" Copyright (c) Michael Smith 2.\" All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions and the following disclaimer. 9.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" notice, this list of conditions and the following disclaimer in the 11.\" documentation and/or other materials provided with the distribution. 12.\" 13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" SUCH DAMAGE. 24.\" 25.\" $FreeBSD$ 26.\" 27.Dd September 9, 2022 28.Dt LIBSA 3 29.Os 30.Sh NAME 31.Nm libsa 32.Nd support library for standalone executables 33.Sh SYNOPSIS 34.In stand.h 35.Sh DESCRIPTION 36The 37.Nm 38library provides a set of supporting functions for standalone 39applications, mimicking where possible the standard 40.Bx 41programming 42environment. 43The following sections group these functions by kind. 44Unless specifically described here, see the corresponding section 3 45manpages for the given functions. 46.Sh STRING FUNCTIONS 47String functions are available as documented in 48.Xr string 3 49and 50.Xr bstring 3 . 51.Sh MEMORY ALLOCATION 52.Bl -hang -width 10n 53.It Xo 54.Ft "void *" 55.Fn malloc "size_t size" 56.Xc 57.Pp 58Allocate 59.Fa size 60bytes of memory from the heap using a best-fit algorithm. 61.It Xo 62.Ft void 63.Fn free "void *ptr" 64.Xc 65.Pp 66Free the allocated object at 67.Fa ptr . 68.It Xo 69.Ft void 70.Fn setheap "void *start" "void *limit" 71.Xc 72.Pp 73Initialise the heap. 74This function must be called before calling 75.Fn alloc 76for the first time. 77The region between 78.Fa start 79and 80.Fa limit 81will be used for the heap; attempting to allocate beyond this will result 82in a panic. 83.It Xo 84.Ft "char *" 85.Fn sbrk "int junk" 86.Xc 87.Pp 88Provides the behaviour of 89.Fn sbrk 0 , 90i.e., returns the highest point that the heap has reached. 91This value can 92be used during testing to determine the actual heap usage. 93The 94.Fa junk 95argument is ignored. 96.El 97.Sh ENVIRONMENT 98A set of functions are provided for manipulating a flat variable space similar 99to the traditional shell-supported environment. 100Major enhancements are support 101for set/unset hook functions. 102.Bl -hang -width 10n 103.It Xo 104.Ft "char *" 105.Fn getenv "const char *name" 106.Xc 107.It Xo 108.Ft int 109.Fn setenv "const char *name" "const char *value" "int overwrite" 110.Xc 111.It Xo 112.Ft int 113.Fn putenv "char *string" 114.Xc 115.It Xo 116.Ft int 117.Fn unsetenv "const char *name" 118.Xc 119.Pp 120These functions behave similarly to their standard library counterparts. 121.It Xo 122.Ft "struct env_var *" 123.Fn env_getenv "const char *name" 124.Xc 125.Pp 126Looks up a variable in the environment and returns its entire 127data structure. 128.It Xo 129.Ft int 130.Fn env_setenv "const char *name" "int flags" "const void *value" "ev_sethook_t sethook" "ev_unsethook_t unsethook" 131.Xc 132.Pp 133Creates a new or sets an existing environment variable called 134.Fa name . 135If creating a new variable, the 136.Fa sethook 137and 138.Fa unsethook 139arguments may be specified. 140.Pp 141The set hook is invoked whenever an attempt 142is made to set the variable, unless the EV_NOHOOK flag is set. 143Typically 144a set hook will validate the 145.Fa value 146argument, and then call 147.Fn env_setenv 148again with EV_NOHOOK set to actually save the value. 149The predefined function 150.Fn env_noset 151may be specified to refuse all attempts to set a variable. 152.Pp 153The unset hook is invoked when an attempt is made to unset a variable. 154If it 155returns zero, the variable will be unset. 156The predefined function 157.Fa env_nounset 158may be used to prevent a variable being unset. 159.El 160.Sh STANDARD LIBRARY SUPPORT 161.Bl -hang -width 10n 162.It Xo 163.Ft int 164.Fn abs "int i" 165.Xc 166.It Xo 167.Ft int 168.Fn getopt "int argc" "char * const *argv" "const char *optstring" 169.Xc 170.It Xo 171.Ft long 172.Fn strtol "const char *nptr" "char **endptr" "int base" 173.Xc 174.It Xo 175.Ft long long 176.Fn strtoll "const char *nptr" "char **endptr" "int base" 177.Xc 178.It Xo 179.Ft long 180.Fn strtoul "const char *nptr" "char **endptr" "int base" 181.Xc 182.It Xo 183.Ft long long 184.Fn strtoull "const char *nptr" "char **endptr" "int base" 185.Xc 186.It Xo 187.Ft void 188.Fn srandom "unsigned int seed" 189.Xc 190.It Xo 191.Ft "long" 192.Fn random void 193.Xc 194.It Xo 195.Ft "char *" 196.Fn strerror "int error" 197.Xc 198.Pp 199Returns error messages for the subset of errno values supported by 200.Nm . 201.It Fn assert expression 202.Pp 203Requires 204.In assert.h . 205.It Xo 206.Ft int 207.Fn setjmp "jmp_buf env" 208.Xc 209.It Xo 210.Ft void 211.Fn longjmp "jmp_buf env" "int val" 212.Xc 213.Pp 214Defined as 215.Fn _setjmp 216and 217.Fn _longjmp 218respectively as there is no signal state to manipulate. 219Requires 220.In setjmp.h . 221.El 222.Sh CHARACTER I/O 223.Bl -hang -width 10n 224.It Xo 225.Ft void 226.Fn gets "char *buf" 227.Xc 228.Pp 229Read characters from the console into 230.Fa buf . 231All of the standard cautions apply to this function. 232.It Xo 233.Ft void 234.Fn ngets "char *buf" "int size" 235.Xc 236.Pp 237Read at most 238.Fa size 239- 1 characters from the console into 240.Fa buf . 241If 242.Fa size 243is less than 1, the function's behaviour is as for 244.Fn gets . 245.It Xo 246.Ft int 247.Fn fgetstr "char *buf" "int size" "int fd" 248.Xc 249.Pp 250Read a line of at most 251.Fa size 252characters into 253.Fa buf . 254Line terminating characters are stripped, and the buffer is always 255.Dv NUL 256terminated. 257Returns the number of characters in 258.Fa buf 259if successful, or -1 if a read error occurs. 260.It Xo 261.Ft int 262.Fn printf "const char *fmt" "..." 263.Xc 264.It Xo 265.Ft void 266.Fn vprintf "const char *fmt" "va_list ap" 267.Xc 268.It Xo 269.Ft int 270.Fn sprintf "char *buf" "const char *fmt" "..." 271.Xc 272.It Xo 273.Ft void 274.Fn vsprintf "char *buf" "const char *fmt" "va_list ap" 275.Xc 276.Pp 277The *printf functions implement a subset of the standard 278.Fn printf 279family functionality and some extensions. 280The following standard conversions 281are supported: c,d,n,o,p,s,u,x. 282The following modifiers are supported: 283+,-,#,*,0,field width,precision,l. 284.Pp 285The 286.Li b 287conversion is provided to decode error registers. 288Its usage is: 289.Bd -ragged -offset indent 290printf( 291.Qq reg=%b\en , 292regval, 293.Qq <base><arg>* 294); 295.Ed 296.Pp 297where <base> is the output expressed as a control character, e.g.\& \e10 gives 298octal, \e20 gives hex. 299Each <arg> is a sequence of characters, the first of 300which gives the bit number to be inspected (origin 1) and the next characters 301(up to a character less than 32) give the text to be displayed if the bit is set. 302Thus 303.Bd -ragged -offset indent 304printf( 305.Qq reg=%b\en , 3063, 307.Qq \e10\e2BITTWO\e1BITONE 308); 309.Ed 310.Pp 311would give the output 312.Bd -ragged -offset indent 313reg=3<BITTWO,BITONE> 314.Ed 315.Pp 316The 317.Li D 318conversion provides a hexdump facility, e.g. 319.Bd -ragged -offset indent 320printf( 321.Qq %6D , 322ptr, 323.Qq \&: 324); gives 325.Qq XX:XX:XX:XX:XX:XX 326.Ed 327.Bd -ragged -offset indent 328printf( 329.Qq %*D , 330len, 331ptr, 332.Qq "\ " 333); gives 334.Qq XX XX XX ... 335.Ed 336.El 337.Sh CHARACTER TESTS AND CONVERSIONS 338.Bl -hang -width 10n 339.It Xo 340.Ft int 341.Fn isupper "int c" 342.Xc 343.It Xo 344.Ft int 345.Fn islower "int c" 346.Xc 347.It Xo 348.Ft int 349.Fn isspace "int c" 350.Xc 351.It Xo 352.Ft int 353.Fn isdigit "int c" 354.Xc 355.It Xo 356.Ft int 357.Fn isxdigit "int c" 358.Xc 359.It Xo 360.Ft int 361.Fn isascii "int c" 362.Xc 363.It Xo 364.Ft int 365.Fn isalpha "int c" 366.Xc 367.It Xo 368.Ft int 369.Fn isalnum "int c" 370.Xc 371.It Xo 372.Ft int 373.Fn iscntrl "int c" 374.Xc 375.It Xo 376.Ft int 377.Fn isgraph "int c" 378.Xc 379.It Xo 380.Ft int 381.Fn ispunct "int c" 382.Xc 383.It Xo 384.Ft int 385.Fn toupper "int c" 386.Xc 387.It Xo 388.Ft int 389.Fn tolower "int c" 390.Xc 391.El 392.Sh FILE I/O 393.Bl -hang -width 10n 394.It Xo 395.Ft int 396.Fn open "const char *path" "int flags" 397.Xc 398.Pp 399Similar to the behaviour as specified in 400.Xr open 2 , 401except that file creation is not supported, so the mode parameter is not 402required. 403The 404.Fa flags 405argument may be one of O_RDONLY, O_WRONLY and O_RDWR. 406Only UFS currently supports writing. 407.It Xo 408.Ft int 409.Fn close "int fd" 410.Xc 411.It Xo 412.Ft void 413.Fn closeall void 414.Xc 415.Pp 416Close all open files. 417.It Xo 418.Ft ssize_t 419.Fn read "int fd" "void *buf" "size_t len" 420.Xc 421.It Xo 422.Ft ssize_t 423.Fn write "int fd" "void *buf" "size_t len" 424.Xc 425.Pp 426(No file systems currently support writing.) 427.It Xo 428.Ft off_t 429.Fn lseek "int fd" "off_t offset" "int whence" 430.Xc 431.Pp 432Files being automatically uncompressed during reading cannot seek backwards 433from the current point. 434.It Xo 435.Ft int 436.Fn stat "const char *path" "struct stat *sb" 437.Xc 438.It Xo 439.Ft int 440.Fn fstat "int fd" "struct stat *sb" 441.Xc 442.Pp 443The 444.Fn stat 445and 446.Fn fstat 447functions only fill out the following fields in the 448.Fa sb 449structure: st_mode,st_nlink,st_uid,st_gid,st_size. 450The 451.Nm tftp 452file system cannot provide meaningful values for this call, and the 453.Nm cd9660 454file system always reports files having uid/gid of zero. 455.El 456.Sh PAGER 457The 458.Nm 459library supplies a simple internal pager to ease reading the output of large 460commands. 461.Bl -hang -width 10n 462.It Xo 463.Ft void 464.Fn pager_open 465.Xc 466.Pp 467Initialises the pager and tells it that the next line output will be the top of the 468display. 469The environment variable LINES is consulted to determine the number of 470lines to be displayed before pausing. 471.It Xo 472.Ft void 473.Fn pager_close void 474.Xc 475.Pp 476Closes the pager. 477.It Xo 478.Ft int 479.Fn pager_output "const char *lines" 480.Xc 481.Pp 482Sends the lines in the 483.Dv NUL Ns 484-terminated buffer at 485.Fa lines 486to the pager. 487Newline characters are counted in order to determine the number 488of lines being output (wrapped lines are not accounted for). 489The 490.Fn pager_output 491function will return zero when all of the lines have been output, or nonzero 492if the display was paused and the user elected to quit. 493.It Xo 494.Ft int 495.Fn pager_file "const char *fname" 496.Xc 497.Pp 498Attempts to open and display the file 499.Fa fname . 500Returns -1 on error, 0 at EOF, or 1 if the user elects to quit while reading. 501.El 502.Sh MISC 503.Bl -hang -width 10n 504.It Xo 505.Ft char * 506.Fn devformat "struct devdesc *" 507.Xc 508.Pp 509Format the specified device as a string. 510.It Xo 511.Ft int 512.Fn devparse "struct devdesc **dev" "const char *devdesc" "const char **path" 513.Xc 514.Pp 515Parse the 516.Dv devdesc 517string of the form 518.Sq device:[/path/to/file] . 519The 520.Dv devsw 521table is used to match the start of the 522.Sq device 523string with 524.Fa dv_name . 525If 526.Fa dv_parsedev 527is non-NULL, then it will be called to parse the rest of the string and allocate 528the 529.Dv struct devdesc 530for this path. 531If NULL, then a default routine will be called that will allocate a simple 532.Dv struct devdesc , 533parse a unit number and ensure there's no trailing characters. 534If 535.Dv path 536is non-NULL, then a pointer to the remainder of the 537.Dv devdesc 538string after the device specification is written. 539.It Xo 540.Ft int 541.Fn devinit void 542Calls all the 543.Fa dv_init 544routines in the 545.Dv devsw 546array, returning the number of routines that returned an error. 547.It Xo 548.Ft void 549.Fn twiddle void 550.Xc 551.Pp 552Successive calls emit the characters in the sequence |,/,-,\\ followed by a 553backspace in order to provide reassurance to the user. 554.El 555.Sh REQUIRED LOW-LEVEL SUPPORT 556The following resources are consumed by 557.Nm 558- stack, heap, console and devices. 559.Pp 560The stack must be established before 561.Nm 562functions can be invoked. 563Stack requirements vary depending on the functions 564and file systems used by the consumer and the support layer functions detailed 565below. 566.Pp 567The heap must be established before calling 568.Fn alloc 569or 570.Fn open 571by calling 572.Fn setheap . 573Heap usage will vary depending on the number of simultaneously open files, 574as well as client behaviour. 575Automatic decompression will allocate more 576than 64K of data per open file. 577.Pp 578Console access is performed via the 579.Fn getchar , 580.Fn putchar 581and 582.Fn ischar 583functions detailed below. 584.Pp 585Device access is initiated via 586.Fn devopen 587and is performed through the 588.Fn dv_strategy , 589.Fn dv_ioctl 590and 591.Fn dv_close 592functions in the device switch structure that 593.Fn devopen 594returns. 595.Pp 596The consumer must provide the following support functions: 597.Bl -hang -width 10n 598.It Xo 599.Ft int 600.Fn getchar void 601.Xc 602.Pp 603Return a character from the console, used by 604.Fn gets , 605.Fn ngets 606and pager functions. 607.It Xo 608.Ft int 609.Fn ischar void 610.Xc 611.Pp 612Returns nonzero if a character is waiting from the console. 613.It Xo 614.Ft void 615.Fn putchar int 616.Xc 617.Pp 618Write a character to the console, used by 619.Fn gets , 620.Fn ngets , 621.Fn *printf , 622.Fn panic 623and 624.Fn twiddle 625and thus by many other functions for debugging and informational output. 626.It Xo 627.Ft int 628.Fn devopen "struct open_file *of" "const char *name" "const char **file" 629.Xc 630.Pp 631Open the appropriate device for the file named in 632.Fa name , 633returning in 634.Fa file 635a pointer to the remaining body of 636.Fa name 637which does not refer to the device. 638The 639.Va f_dev 640field in 641.Fa of 642will be set to point to the 643.Vt devsw 644structure for the opened device if successful. 645Device identifiers must 646always precede the path component, but may otherwise be arbitrarily formatted. 647Used by 648.Fn open 649and thus for all device-related I/O. 650.It Xo 651.Ft int 652.Fn devclose "struct open_file *of" 653.Xc 654.Pp 655Close the device allocated for 656.Fa of . 657The device driver itself will already have been called for the close; this call 658should clean up any allocation made by devopen only. 659.It Xo 660.Ft void 661.Fn __abort 662.Xc 663.Pp 664Calls 665.Fn panic 666with a fixed string. 667.It Xo 668.Ft void 669.Fn panic "const char *msg" "..." 670.Xc 671.Pp 672Signal a fatal and unrecoverable error condition. 673The 674.Fa msg ... 675arguments are as for 676.Fn printf . 677.El 678.Sh INTERNAL FILE SYSTEMS 679Internal file systems are enabled by the consumer exporting the array 680.Vt struct fs_ops *file_system[] , 681which should be initialised with pointers 682to 683.Vt struct fs_ops 684structures. 685The following file system handlers are supplied by 686.Nm , 687the consumer may supply other file systems of their own: 688.Bl -hang -width ".Va cd9660_fsops" 689.It Va ufs_fsops 690The 691.Bx 692UFS. 693.It Va ext2fs_fsops 694Linux ext2fs file system. 695.It Va tftp_fsops 696File access via TFTP. 697.It Va nfs_fsops 698File access via NFS. 699.It Va cd9660_fsops 700ISO 9660 (CD-ROM) file system. 701.It Va gzipfs_fsops 702Stacked file system supporting gzipped files. 703When trying the gzipfs file system, 704.Nm 705appends 706.Li .gz 707to the end of the filename, and then tries to locate the file using the other 708file systems. 709Placement of this file system in the 710.Va file_system[] 711array determines whether gzipped files will be opened in preference to non-gzipped 712files. 713It is only possible to seek a gzipped file forwards, and 714.Fn stat 715and 716.Fn fstat 717on gzipped files will report an invalid length. 718.It Va bzipfs_fsops 719The same as 720.Va gzipfs_fsops , 721but for 722.Xr bzip2 1 Ns -compressed 723files. 724.El 725.Pp 726The array of 727.Vt struct fs_ops 728pointers should be terminated with a NULL. 729.Sh DEVICES 730Devices are exported by the supporting code via the array 731.Vt struct devsw *devsw[] 732which is a NULL terminated array of pointers to device switch structures. 733.Sh DRIVER INTERFACE 734The driver needs to provide a common set of entry points that are 735used by 736.Nm libsa 737to interface with the device. 738.Bd -literal 739struct devsw { 740 const char dv_name[DEV_NAMLEN]; 741 int dv_type; 742 int (*dv_init)(void); 743 int (*dv_strategy)(void *devdata, int rw, daddr_t blk, 744 size_t size, char *buf, size_t *rsize); 745 int (*dv_open)(struct open_file *f, ...); 746 int (*dv_close)(struct open_file *f); 747 int (*dv_ioctl)(struct open_file *f, u_long cmd, void *data); 748 int (*dv_print)(int verbose); 749 void (*dv_cleanup)(void); 750 char * (*dv_fmtdev)(struct devdesc *); 751 int (*dv_parsedev)(struct devdesc **dev, const char *devpart, 752 const char **path); 753 bool (*dv_match)(struct devsw *dv, const char *devspec); 754}; 755.Ed 756.Bl -tag -width ".Fn dv_strategy" 757.It Fn dv_name 758The device's name. 759.It Fn dv_type 760Type of device. 761The supported types are: 762.Bl -tag -width "DEVT_NONE" 763.It DEVT_NONE 764.It DEVT_DISK 765.It DEVT_NET 766.It DEVT_CD 767.It DEVT_ZFS 768.It DEVT_FD 769.El 770Each type may have its own associated (struct type_devdesc), 771which has the generic (struct devdesc) as its first member. 772.It Fn dv_init 773Driver initialization routine. 774This routine should probe for available units. 775Drivers are responsible for maintaining lists of units for later enumeration. 776No other driver routines may be called before 777.Fn dv_init 778returns. 779.It Fn dv_open 780The driver open routine. 781.It Fn dv_close 782The driver close routine. 783.It Fn dv_ioctl 784The driver ioctl routine. 785.It Fn dv_print 786Prints information about the available devices. 787Information should be presented with 788.Fn pager_output . 789.It Fn dv_cleanup 790Cleans up any memory used by the device before the next stage is run. 791.It Fn dv_fmtdev 792Converts the specified devdesc to the canonical string representation 793for that device. 794.It Fn dv_parsedev 795Parses the device portion of a file path. 796The 797.Dv devpart 798will point to the 799.Sq tail 800of device name, possibly followed by a colon and a path within the device. 801The 802.Sq tail 803is, by convention, the part of the device specification that follows the 804.Fa dv_name 805part of the string. 806So when 807.Fa devparse 808is parsing the string 809.Dq disk3p5:/xxx , 810.Dv devpart 811will point to the 812.Sq 3 813in that string. 814The parsing routine is expected to allocate a new 815.Dv struct devdesc 816or subclass and return it in 817.Dv dev 818when successful. 819This routine should set 820.Dv path 821to point to the portion of the string after device specification, or 822.Dq /xxx 823in the earlier example. 824Generally, code needing to parse a path will use 825.Fa devparse 826instead of calling this routine directly. 827.It Fn dv_match 828.Dv NULL 829to specify that all device paths starting with 830.Fa dv_name 831match. 832Otherwise, this function returns 0 for a match and a non-zero 833.Dv errno 834to indicate why it didn't match. 835This is helpful when you claim the device path after using it to query 836properties on systems that have uniform naming for different types of 837devices. 838.El 839.Sh HISTORY 840The 841.Nm 842library contains contributions from many sources, including: 843.Bl -bullet -compact 844.It 845.Nm libsa 846from 847.Nx 848.It 849.Nm libc 850and 851.Nm libkern 852from 853.Fx 3.0 . 854.It 855.Nm zalloc 856from 857.An Matthew Dillon Aq Mt dillon@backplane.com 858.El 859.Pp 860The reorganisation and port to 861.Fx 3.0 , 862the environment functions and this manpage were written by 863.An Mike Smith Aq Mt msmith@FreeBSD.org . 864.Sh BUGS 865The lack of detailed memory usage data is unhelpful. 866