LIBSTAND(3)

名称
libstand - スタンドアローン実行用サポートライブラリ

書式
<stand.h>

解説
libstand は、スタンドアローンアプリケーションのサポート関数群と、 標準 BSD プログラミングが可能な模擬環境を備えています。 後のセクションでこれらの関数を種類分けしています。 ここに明確な定義がない場合は、指定の関数のセクション 3 の マニュアルページの該当個所を参照して下さい。

文字列関数
使用できる文字列関数は、 string(3) および bstring(3) に書かれています。

メモリアロケーション

    void * malloc(size_t size)

    size で指定した大きさのメモリを最適なアルゴリズムでヒープ領域から割り 当てます。

    void free(void *ptr)

    ptr に割り当てられたオブジェクトを解放します。

    void setheap(void *start, void *limit)

    ヒープ領域を初期化します。この関数は、 alloc() を最初に呼び出す前に実行しなければなりません。 start と limit の間の領域がヒープ領域に使用されます。 これを越えて割り当てようとすると panic となります。

    char * sbrk(int junk)

    sbrk(0) の性質を与えます。すなわちヒープ領域の最高位アドレスのポインタを 返します。この戻り値は、テスト時にヒープの実使用状況を判断するのに 使用できます。引数 junk は無視されます。

環境
伝統的なシェルサポート環境と同様、フラットな変数空間操作のために 一群の関数が備わっています。主な拡張として、フック関数の設定／設定解除の ためのサポートがあります。

    char * getenv(const char *name)

    int setenv(const char *name, char *value, int overwrite)

    int putenv(const char *string)

    int unsetenv(const char *name)

    これらの関数は、標準ライブラリと類似の動作をします。

    struct env_var * env_getenv(const char *name)

    その環境内での変数を検索し、すべてのデータ構造を返します。

    int env_setenv(const char *name, int flags, char *value, ev_sethook_t sethook, ev_unsethook_t unsethook)

    name という環境変数の新規作成または既存環境変数の設定を行います。 新規変数を生成する場合は、引数 sethook および unsethook を指定することができます。

    EV_NOHOOK フラグが設定されていなければ、変数設定をしようとするとすると、 フックの設定が必ず起動されます。通常、引数 value の確認を行ない、実際に値を保存するために EV_NOHOOK 変数をつけて、再度 env_setenv() 呼び出しを行い設定します。すべての変数設定を拒否するために、定義済み関数 env_noset() を指定することができます。

    設定解除フックは、変数の設定解除が行われるときに起動されます。 戻り値が 0 のとき、変数の設定解除されています。定義済み関数 env_nounset は、変数設定解除を抑制するのに使用します。

標準ライブラリサポート

    int getopt(int argc, char * const *argv, cont char *optstring)

    long strtol(const char *nptr, char **endptr, int base)

    void srandom(unsigned long seed)

    unsigned long random(void)

    char * strerror(int error)

    libstand でサポートされている errno のサブセット値に対応する エラーメッセージを返します。

assert(expression)

    <assert.h> 行が必要です。

    int setjmp(jmp_buf env)

    void longjmp(jmp_buf env, int val)

    操作できるシグナル状態がないため、それぞれ _setjmp() および _lonjmp() として定義されています。 <setjmp.h> 行が必要です。

キャラクタ I/O

    void gets(char *buf)

    キャラクタをコンソールから buf に読み込みます。標準的な注意事項が本関数に 対して適用されます。

    void ngets(char *buf, size_t size)

    size -1 またはそれ以下の文字をコンソールから buf に読み込みます。行末文字は削除され、 バッファは常にヌルが終端文字になります。 size が 1 以下の場合、関数は gets() と同じ動作をします。

    int fgetstr(char *buf, int size, int fd)

    一行を size 文字以下の範囲で buf に読み込みます。行末のキャラクタは切り捨てられ、 バッファは常にヌルが終端となります。 正常終了のときは buf 内の文字数を返し、読み込みエラーのときは -1 を返します。

    int printf(const char *fmt, ...)

    void vprintf(const char *fmt, va_list ap)

    int sprintf(char *buf, const char *fmt, ...)

    void vsprintf(char *buf, const char *fmt, va_list ap)

    *printf 関数は、標準 printf() ファミリのサブセット機能といくつかの拡張機能を備えています。 c,d,n,o,p,s,u,x の標準変換がサポートされています。 +,-,#,*,0, field width,precision,l の修飾子がサポートされています。

    エラーレジスタをデコードするために b 変換が備わっています。 使い方は以下の通りです。

    printf( "reg=%b\n", regval, "<base><arg>*" );

    <base> は、制御キャラクタの出力を表現しています。例えば \10 は 10 進数を、\20 は 16 進数を意味します。各 <arg> は、文字列で、最初の一文字は引数のビット数(始めが1)で、 ビットが設定されている場合、それ以降の文字列(32文字未満)は表示対象の テキストです。つまり、

    printf( "reg=%b\n" 3 "\10\2BITTWO\1BITONE\n" );

    により出力表示されます。

    reg=3<BITTWO,BITONE>

    D 変換は、16 進数ダンプの機能を備えています。 たとえば、以下。

    printf( "%6D", ptr, "": ); gives "XX:XX:XX:XX:XX:XX"

    printf( "%*D", len, ptr, " " ); gives "XX XX XX ..."

文字テストと変換

    int isupper(int c)

    int islower(int c)

    int isspace(int c)

    int isdigit(int c)

    int isxdigit(int c)

    int isascii(int c)

    int isalpha(int c)

    int toupper(int c)

    int tolower(int c)

ファイル入出力

    int open(const char *path, int flags)

    open(2) の動作に似ています。ただし、ファイル作成機能がサポート されていないため、モードパラメータは不要です。引数 flags には、O_RDONLY, O_WRONLY, O_RDWR のどれかを指定できます。 (たとえ、現在書込みをサポートするファイルシステムが無いとしても)

    int close(int fd)

    void closeall(void)

    すべての open されているファイルを閉じます。

    ssize_t read(int fd, void *buf, size_t len)

    ssize_t write(int fd, void *buf, size_t len)

    (現在書き込みをサポートしているファイルシステムはありません)

    off_t lseek(int fd, off_t offset, int whence)

    読み込みの最中に自動的に解凍されるファイルは、現在の位置から後方に seek することはできません。

    int stat(const char *path, struct stat *sb)

    int fstat(int fd, struct stat *sb)

    関数 stat() および fstat() は、 sb 構造体のフィールド : st_mode, st_nlink,st_uid,st_gid,st_size への書き込みだけをします。 tftp ファイルシステムでは、この関数の呼び出しは 意味のある値になりません。また cd9660 ファイルシステムは、ファイルの uid/gid が常に 0 であると 報告して来ます。

ページャ
libstand は簡単な内部ページャを提供し、大きなコマンドの出力を読みやすくします。

    void pager_open()

    ページャを初期化し、次の出力行が表示装置の先頭であることを知らせます。 環境変数 LINES は、一度に表示可能な行数を決める際に参照されます。

    void pager_close(void)

    ページャを閉じます

    int pager_output(char *lines)

    lines で指定された、ヌルで終了するバッファの行がページャに送られます。 改行文字を数えることで、出力される行数が決まります。 (折り返しは含みません) すべての行が出力されると、 pager_output() は 0 を返します。画面表示が停止し、ユーザが途中終了を 選択したときは 0 以外の値を返します。

    int pager_file(char *fname)

    ファイル fname を開き、画面表示します。エラーのときは -1 を返し、EOF のときは 0 を、ユーザが読み込みを途中終了する場合は 1 を返します。

その他

    void twiddle(void)

    連続呼び出しの場合、ユーザが確認できるように、 文字列 |,/,-,\ の後にバックスペースを付けて出力します。

低レベルサポートの要求
スタック、ヒープ、コンソール、デバイスは、 libstand でよく使われるリソースです。

スタックは、 libstand 関数が起動される前に構築する必要があります。 スタック要求は、関数や使われているファイルシステム、および、後で詳述する サポートレイヤ関数によって変化します。

ヒープは、 alloc() 関数や open() 関数の呼び出しの前に、 setheap() 呼び出しを行なって構築しなければなりません。ヒープの使用法は、クライアントの 動作と同様、同時に open するファイルの数によって変化します。自動解凍をす ると、ファイルを open する度に 64K 以上のデータが割り当てられます。

コンソールアクセスは、後述の関数 getchar(), putchar(), ischar() によって行われます。

デバイスアクセスは devopen() によって初期化され、 devopen() が返すデバイススイッチ構造体の関数 dv_strategy(), dv_ioctl(), dv_close() によって実行されます。

ユーザは次のサポート関数を用意する必要があります。

    int getchar(void)

    コンソールから、関数 gets(), ngets() やページャ関数によって使われる文字を返します。

    int ischar(void)

    コンソールから入力待ちの状態のとき、0 でない値を返します。

    void putchar(int)

    コンソールに、 gets(), ngets(), *printf(), panic(), twiddle() および 他の多くのデバッグ、情報通知用の関数が使用する文字を書き出します。

    int devopen(struct open_file *of, const char *name, char **file)

    name という名前のファイル用の適当なデバイスを開き、デバイスを参照しない ファイルの残りの部分の name を指すポインタを、 file に返します。 of の構造体フィールド f_dev は、正常終了した場合、open したデバイスの devsw 構造体を指すようにセットされます。 デバイス識別子は、常にパス構成の先頭に来る 必要がありますが、それ以外は自由にフォーマットされています。 open() や デバイス関連の I/O で使用されます。

    int devclose(struct open_file *of) of に割り当てられたデバイスを閉じます。 デバイスドライバ自身はクローズ処理のためにすでに呼び出しが行われており、 この呼び出しは、 devopen() による割り当てを解除するだけです。

    void panic(const char *msg, ...)

    致命的で回復不能なエラー状態を通知します。引数 msg ... は、 printf() のものと同様です。

内部ファイルシステム
内部ファイルシステムでは、 struct fs_ops *file_system[] の構造体の配列を、ユーザ がエクスポートでき、配列は構造体 struct fs_ops へのポインタで初期化されます。 以下のファイルシステムハンドラが libstand に 備わっていますが、ユーザは自分で別のファイルシステムを 提供することができます。

ufs_fsops
    BSD の UFS

ext2fs_fsops
    Linux の ext2fs ファイルシステム

tftp_fsops
    TFTP 経由のファイルアクセス

nfs_fsops
    NFS 経由のファイルアクセス

cd9660_fsops
    ISO 9660 (CD-ROM) ファイルシステム

zipfs_fsops
    ファイルをサポートしているファイルシステムの gzip されたファイルをサポートするスタック されたファイルシステムで、zipfs ファイルシステムを使おうとすると、 libstand はファイル名の後に .gz を付加し、更に別のファイルシステムを使用してファイルの位置を決めます。 このファイルシステムの、配列 file_system[] での配置によって、 non-gzipped ファイルを参照している gzipped ファイルが open されるかどうかが決められます。 gzip されたファイルは前方へ seek することだけができ、gzip されたファイルへの stat() および fstat() は、長さの不正を報告します。

bzipfs_fsops
    zipfs_fsops と同様ですが、 bzip2 で圧縮されたファイルを使用します。

構造体 struct fs_ops のポインタ配列はヌルで終了しなければなりません。

デバイス
デバイスは、ヌルで終了するデバイススイッチ構造体のポインタ配列である、 struct devsw *devsw[] 経由のサポートコードによってエクスポートされます。

バグ
詳細なメモリ使用データがないのは不親切です。

歴史
libstand は多くのソースを利用しています。すなわち、
•   NetBSD からの libsa
•   FreeBSD 3.0 からの libc と libkern
•   Matthew Dillon <dillon@backplane.com> からの zalloc

再構成と FreeBSD 3.0 へのポート、環境変数関係の関数、このマニュアルページは Mike Smith <msmith@FreeBSD.org> が作成しました。