取得 - みる会図書館


検索対象: 月刊 C MAGAZINE 1991年8月号
57件見つかりました。

1. 月刊 C MAGAZINE 1991年8月号

特集認プログラミンク入門 List 1 ットワークアドレスはいくつなのかを表示 します。 接続状況を知るには , まず接続番号を取 得しなければなりません。接続番号により ューザ名 , オプジェクトタイプ , ログイン した時間 , 端末のノードアドレスなどが得 られます。 次に , サーバ名を知るためには接続 ID を 取得しなければなりません。 ReadP 「 opertyValue 関数 プログラムは大きく次のように流れてい 所属グループのプロバティを取得 きます。 NetWare が標準て、サポートしている フルネームを取得した際に使った関数を , ①接続番号の取得 whoami. exe コマンドをまねて作ったものて、 再度 , グループ ID を調べるために使いま ②接続情報の取得 す。グループ ID は , long 型の配列として値 す。 ③現在接続中のサーバ名の取得 ネットワークにログインしている状態て、 , を返されます。 自分がいつログインしたのか , 自分が接続 ④ネットワークアドレスの取得 GetBinderyObjectName 関数 しているサーバはどれか , 自分の端末のネ グループ D からグループ名を取得 グループ名はグループ ID から導きます。 この関数て、はオプジェクトの ID を入力する Table 2 ことによりオプジェクト名を返します。 オプジェクトタイプ の際 , ReadPropertyValue 関数て、得たグル ユーサ ープの ID は , バイト列が逆になっているた ユーサグループ めこれを LongSwap 関数て、元に戻します。 プリントキュー の LongSwap 関数は Miscellaneous Ser ファイルサーバ vices として提供されています。 ジョブサーバ グループ ID は配列という形て汚・えられる ゲートウェイ ため , 配列の内容が NULL となるまて、ルー プリントサーバ プしてオプジェクト名を調べていきます。 プリントキューユーサ 7 ー 8 0 ) 8 8 8 8 return( 0 ) : ョン API サービスを用いて取得 , 設定て、きま す (Fig. 12 ) 。 オプジェクト名からグレープ D を 調へ , ツループ名を取得 ログラム netwami. c (List 2 ) ヘッダファイルの中の定義 OT USER OT USER GROUP OT PRINT QUEUE OT FILE SERVER OT JOB SERVER OT GATEWAY OT PRINT SERVER 実際の値 0X01 0X02 0X03 0X04 0X05 0X06 0X07 OT PRINT QUEUE USER 0X53 コネクションと WS 環境サービス 端末とファイルサーバの接続をコネクシ ョンと呼びます。端末は同時に最大 8 個のサ ーバと接続が可能て、す。 端末て、はファイルサーバの名前やネット ワークアドレス , 対応するネットワークド ライプやディレクトリなど , 個々の接続に 関する情報を接続 ID をキーにして格納して います。 これらの情報はワークステーション API サ ービスを用いて取得 , 設定て、きます。 ファイルサーバは複数の端末と接続て、き ます。ファイルサーバ側て、は , 接続番号を キーとして個々のコネクションに関する情 報を格納しています。この情報はコネクシ バとワークステーションの接続 Fig. 12 ファイルサー サーバ # 2 SYS :WORK 接続番号 = 1 サーバ # 1 接続番号 = 1 SYS : MAIN 接続番号 = 2 接 D = 2 接続 = 2 接続 = 1 F . ワークステーション # 1 ワークステーション # 2 特集 LAN プログラミング入門 63

2. 月刊 C MAGAZINE 1991年8月号

ネットワークプリンタにキャプチャーの設定なしに ファイルを直接出力する (netprint. c) GetVOIumeInf0WithHandIe 関数 ポリューム情報の取得 ポリューム情報をディレクトリハンドル から取得します。入力にディレクトリハン ドルを指定することにより , 出力としてポ リュームネームやポリュームサイズを導く ための値などが得られます。 IsV3Supported 関数 NetWare のバージョンを取得 NetWare のバーションを調べます。通 常 , NetWare v2.2 と NetWare v3. IJ て、は ディレクトリやファイル情報の管理が異な るため , ノヾーションの違いによってファイ ル操作 , ディレクトリ操作を変えなければ なりません。 ティレトリ情報の取得 NetWare の API にはディレクトリサーチ 関数があります。この関数は Turbo C 十十 て、の findfirst, findnext 関数に相当します。 なお , それらはディレクトリとファイルを 同時にサーチて、きたのに対して , ディレク トリ , またはファイルという単位て、しかサ ーチをすることがて、きません。 ScanDirEntry 関数 ディレクトリの情報を取得 ディレクトリの情報をスキャンします。 この関数はループになっていて , ディレク トリ情報がなくなるまて、ループを続けます。 こて、は , 以前に調べておいた接続番号 とディレクトリハンドルとサーチ条件を入 力することにより , ディレクトリ情報を取 得てきます。 この関数は NWDIR ENTRY 構造体を使 ってサーチしますが , このときに使う構造 体を TabIe 3 に示します。 ファイ丿情報の取得 4 に #include <stdio. h> 2 : #include く stdlib. h> 3 : #include く string. h> 4 : #include く conio. h 〉 5 : # i nc 1 ude く i 0. h> 6 : #include く fcntl. h> 7 : #include く nit. h> 8 : #include く niterror. h> 9 : 10 : #define SIZE-OF-SET_CAPTURE 42 12 : void DisplayCapturePIags (void) : 13 : 14 : char buffer[50] : 15 : CAPTURE_FLAGS capflags; 16 : SET_CAPTURE_FLAGS setcapf lags : 18 : void 19 : main( int argc, char *argv[] ) 20 : { 。ー / * プリントアウトをするファイル名 * / 21 : Char *filename; 22 : int default し PTDevice; / * プリンタ ID 23 : WORD connect i 0 ⅲ D : / * 接続 ID * / 24 : long queueID; / * プリントキューⅢ * / 25 : FILB *fpl, *fp2: ノ * ファイルポインタ * / 26 : i nt comp let i onCode, c : if (argc ! = 2 ) { 28 : 29 : fpr intf(stderr, ” Usage: nprint2 fileYn") ; 30 : exit(l); filename ド argv[l] : / * get fi lename * / 32 : 33 : / * 現在のキャプチャーフラグ情報を取得 * / 34 : 35 : compIetionCode = GetDefaultCaptureF lags (&capflags) : 、 36 : if ( completionC0de ! = SUCCESSFUL ) { fprintf(stderr, "GetDefaultCaptureFlags キャプチャーフラグ情報を 37 : 38 : exit(l); 39 : 得られません \ n 工ラーコード : %02XYn", compIetionCode ) : 40 : / * 現在のキャプチャーフラグの表示 * / DispIayCaptureFIags() : 42 : 43 : / * 現在のキャプチャーフラグの内容をセットキャプチャーフラグにセットする * / 44 : memcpy (&setcapflags, &capflags, SIZE-OF_SET CAPTURE ) : 45 : 46 : / * 出力する枚数を 2 部に設定こデフォルトは 1 部 * / setcapf 1 ags. numberOfCop i es = 2 : 49 : / * キャプチャーフラグをセットする * / 50 : 51 : compIetionC0de = SetDefaultCaptureFlags (&setcapflags) : ⅱ ( completionC0de ! ニ SUCCESSFU し ) { 52 : fprintf(stderr, "SetDefaultCaptureFlags (NEW) 新しいキャプチャーフラグ 53 : exit(l); 54 55 をセットできませんでした \ n 工ラーコード : %02XYn", completionCode ) : 56 / * ローカルプリンタの番号を取得 * / 58 defaultLPTDevice GetDefaultLocalPrinter() : / * フ。リントキュー " PR TQ ー 0 " のバインダリオプジェクト ID を取得 * / 60 completionC0de ま GetBindery0bjectID("PRlNTQ_0", OT_PRINT_QUEUB, &queueID) : 62 if ( compIetionC0de ! = SUCCESSPU し ) { 63 fprintf(stderr, "GetBindery0bjectID(PRINTQUEUB) プリントキューのを 64 exit(l); 65 66 取得できませんでした \ n 工ラーコード : % 02X \ n completionCode ) : / * 接続の取得 * / 68 connect i 0 ⅲ D = GetDefau 1 tConnect i on I D ( ) : 69 (BYTE)connectionlD, queueID) : / * プリントキューの設定 * / 70 comp 1 et i onC0de = SetCapturePr i ntQueue ( (BYTE) defau 1 t し PTDev i ce, if ( completionCode ! = SUCCBSSFU し ) { 73 : fprintf(stderr, ” SetCapturePrintQueue プリントキューの ID を取得でき exit(l); 75 : 76 : ませんでした \ n 工ラーコード : %02XYn"„ completionCode ) : / * プリンタキャプチャーを開始する * / 77 : 78 : comp let i onC0de = StartL PTCapture ( ) ; 79 : if ( complet ionCode ! = SUCCESSFU し ) { 80 : fprintf(stderr, ・・ StartLPTCapture プリントキューのを取得でぎません exit(l): 82 : でした Yn 工ラーコード : %02XYn", compIetionCode ) : 84 : / * 出力するファイルをリードオンリーモードでオープンする * / 85 : ScanFiIeEntry 関数 ファイルの情報を取得 ファイルの情報をスキャンします。 ては , ループになり , ファイル情報 , ディ 68 C MAGAZINE 1 1 8

3. 月刊 C MAGAZINE 1991年8月号

す。それを真に受けて , 「 C 十十ては new を 使うのが作法なんだ」みたいに思いこむ人が いるとしたら , かえって逆効果だといわざ るを得ません。 とはいえ , new を malloc ( ) の代替品のよ うに使うのが , もっとも多い用法てあるこ とは間違いありません。まずはこの用法か ら見ていきましよう。 List 5 ( a ) は C 十十プログラマのバイプル 「プログラミング言語 C 十十』にも登場する 定番サンプルて、す。しかし , これを List 5(b) のように malloc ( ) を使って書いたところ て , 使い勝手に差が現れるとは思われませ ん。それなのに「 C 十十て、はこのように書き ます」と押しつけられても困ります。まるて、 抱き合わせ販売てす。 これが char のような組み込み型て、はな く , ユーザ定義の型てある構造体をヒープ に取得するような場合には , やや事情が違 ってきます。 struct MyStruct があったと き ,List 6 ( a ) よりも List 6 ( b ) がシンプルだ し , sizeof ( ) がいらない分だけ , なんとなく 安全そうて、す。かといって , なるほど便利 だ , これなら malloc ( ) とはおさらばさ , と いうほどの違いはありません。 new が単なる malloc ( ) の代替品としての 衣を脱ぎ捨てて , その本領を発揮するのは , 初期値の指定を伴ったときて、す。 「 , : 覇値の指定を伴う new new に初期値を指定するには , new 型 ( 式 ) という書式を使います。たとえば , new int(2) ; int* a という初期化式文ては , new は intl 個分のメ モリを確保したのち , そのメモリを値 2 て、初 期化します。 C 十十の大目的のひとつは「初期化忘れ」を 減らすことにあります。宣言だけされて , 中身が不定のままほったらかしの変数をな るべくなくそう , という考えてす。 こて単に 138 C MAGAZINE 1991 8 List new と malloc (a) char* my_strdup(const char* s) new char[strlen(s) + 1]; char* p if (p) strcpy(), S) : return p; (b) char* 0 = (char*)malloc(strlen(s) + 1) ; int* a List (a) 構造体をヒープに取得するような場合 new int ; MyStruct* p = MyStruct* p (MyStruct*)malloc(sizeof(MyStruct)) ; new MyStruct; としただけて、は , ポインタとしての a は初期 化されるとしても , 実体としての * a は不定 のまま残されています。しかし , new に初期 値を指定することによって , ポインタを宣 言と同時に初期化し , さらにはそのポイン タが指している実体をも初期化することが て、きるのて、す。 「一 c 訓 oc ( ) , realloc( ) new 型 ( 式 ) という書式の下線部だけを取り 出して眺めると , キャストの書式にそっく りて、あることに気づきます。ご存知のよう に C 十十て、は , 従来の ( 型 ) 値という形に加え て , 型 ( 値 ) という書式のキャストも導入さ れています。しかし , new int [ 10 ] (0) : int* i のような初期化式て、はこの類似は崩れます。 一次元配列を取得していますが , あたか も配列要素を 0 て、初期化しているかのように 見えます。実際にそのとおりなのて、すが , , こて、初期化されるのは , あくまて、も配列 の最初の要素だけにとどまることに注意し てください。 2 番目から 10 番目まて、の残りの 要素は不定のまま残されています。配列の 各要素に別々の初期値を設定したり , ある いは , 全要素に共通の初期値をえたりす る手段は提供されていません。 すべての要素を 0 て、初期化したい場合に限 りますが , List 7 (a) のようにする手はあり ます。しかし , どうしても new に固執するの て、あれば , List 7 ( b ) のように , 明示的に 0 て、 埋めつくす以外にありません。やつばり , 初めから calloc ( ) を使ったほうが話が早い し , 宣言と同時に初期化するという理念に もかなっているという気がします。 また , new て、取得されたメモリに対して , reall 。 c ( ) に相当する操作をほどこす方法も ありません。 new は , 型名を指定することか らもわかるように , ある型の実体を確保す ることだけを目的にしているのてあって , ヒープから可変長のメモリのかたまりをぶ んどってくるような処理にはまるつきり向 いていません。 このように , malloc ( ) ファミリーと比較 すると new にも一長一短あります。 「 malloc ( ) もいいけど , new もあるて、よ」く らいに柔軟にとらえていればいいような気 もします。 けれども , new は動的メモリ取得のためだ けに使われているのて、はありません。、、初期 化〃という副作用があることを忘れてはい けません。 拡張された構造体て、ある C 十十のクラスに は , 、、コンストラクタ〃と呼ばれる機構が備

4. 月刊 C MAGAZINE 1991年8月号

て見ていることになります。 接続番号からネットワーク番号とノード ノードアドレスはイーサネットのネット アドレスを得ます。ネットワーク番号はひ ワークポード固有のネットワークアドレス とつのセグメント内 ( インタネットワーク ) て、 , 世界にひとっしかないアドレスて、す。 が表される番号のことて、 , セグメントはす べて同じ番号となります。 したがって , ひとつのセグメント内にあ るサーバのネットワーク番号はすべて同じ NetWare て、はシェルにより ,MS-DOS の て、す。 たとえば , NetWare が標準て、サポートし ファイル , ディレクトリとまったく同じよ ている slist. exe などて、ネットワーク番号が異 うに扱うこともて、きますが , NetWare とし ての特有のサービスを受ける場合にはファ なるサーバが表示されたら , それはセグメ ント外のネットワークをプリッジを経山し イルおよびディレクトリサービスの API を使 ネットワークへの接続状況を表示する (netwami. c) 接続番号の取得 GetConnectionNumber 関数 サーバとの接続番号を取得 ファイルサーバの接続番号を取得します。 接続情報の取得 ファイルおよび ティレクトリサービス GetConnectionlnformation 関数 ーー接続情報を取得 指定した接続ヘログインしているオプジ ェクトの情報を取得します。この関数て、は 以下の情報を得ることがて、きます。 ・オプジェクト名 ・オプジェクトタイプ ・オプジェクトの ID ・ログイン時間 オプジェクトのタイプは finger. c て、説明し こて、は , オプジェ た値が出力されます。 クトは自分自身なのて、オプジェクト名は自 分のログイン名 , オプジェクトのタイプは ューザとなります。 現在接続中のサーバ名の取得 lSt 1 : #include く stdio. h 〉 2 : #inc lude く process. h> 3 : #include く nit. h> 4 : #include く niterror. h> 5 : 6 : void 7 : main(int argc, char *argv[]) 9 : WORD connectionNumber; WORD objectType : long 0bjectID; 12 : IoginTime[7] : BYTB user[48] : 13 : Char WORD connect i on ー D : serverNameC48] : Char network [ 4 ] , node [ 6 ] : 16 : Char 17 : WORD socket; int completionCode; / * 接続番号を取得 * / 20 : 21 : connect i onNumber ニ GetConnec t i onN umber ( ) : if (connectionNumber ー ニ 0 ) { 22 : printf ("NetWare shell not IoadedYn") : 23 : exit(l); 24 : 25 : 26 : &objectType. &objectID, loginTime) : / * 接続情報を取得 * / 27 : 28 : completionCode = GetConnect ionl nformation(connectionNumber, user, if ( compIetionCode ! = SUCCESSFUL ) { 29 : fprintf (stderr, "GetConnectionInfomat ion 接続情報を得られません 30 : exit(l); 32 : Yn 工ラーコード : %02XYn", compIetionCode ) : 33 : / * 現在接続しているサーバーの接続 ID を取得 * / 34 : 35 : connectionID = GetDefaultConnectionID() : 36 : / * ファイルサーバー名を取得 * / GetFi leServerName(connectionID, serverName) ; 38 : 39 : / * ログイン情報の表示 * / 40 : printf(" ユーザ %s はサーバー %s に " user, serverName ) : printf(" %d-%d-%d %d:%d にログインしました \ n " , 42 : IoginTimeC0], IoginTime[I), IoginTime[2], 43 : loginTime[3], loginTime[4) ) : printf(" ワークステーションの接続は %d , 接続番号は %d です \ n " 44 : 45 : / * インターネットワーク情報の取得 * / [ ーー connectionl D, connectionNumber) : 46 : compIetionCode = GetInternetAddress(connectionNumber, network, node, &socket) : 48 : i f ( compIetionCode ! ニ SUCCESSFUL ) { fprintf (stderr, "GetInternetAddress インターネットワーク情報を 49 : exit(l); 50 : 得られません \ n 工ラーコード : %02XYn", completionCode ) : 52 : / * ネットワークアドレス等の表示 * / 53 : printf( " ソケット番号 : % 04X 54 : ”ノードアドレス : % 081X % 04X 55 : " ネットワーク : % 08 Ⅸ Yn", 56 : I ntSwap (socket) , IntSwap(*((int * ) (node + 4 ) ) ) , LongSwap(* ( long *)node) ) , LongSwap(* ( long *)network))) : 59 : 60 : } ス レ ア ノ 番 * ク号ド トト目 * ワトコ * クク時 * / 名トツ一 号工エン名 * 一ッケラ 番ジジイザバネソ工 続ププグ一続一 * * * 接オオロュ接サ / / / GetDefauItConnectionID 関数 接続中のサーバへの接続を取得 この接続 ID は接続番号とは異なり , 今自 分が接続しているいくつかのサーバのうち , 実際にサービスを求めているサーバが何番 目かを示すものて、す。接続番号とは , サー バに接続している端末のうち , サーバにサ ービスを求めてきた端末が何番目て、あるか を示すものて、す。 GetFiIeServerName 関数 サー / ヾ名を取得 接 *%ID によりサーバ名を得ます。 ネッワークアドレスの取得 GetInternetAddress 関数 ネットワーク番号 , ノードアドレスを取得 64 C MAGAZINE 1991 8

5. 月刊 C MAGAZINE 1991年8月号

特集△プログラミンク入門 駐させます。 IPX.COM はネットワークとの接続につい て , プロトコルに関する部分を処理します。 これは , NET3.COM から渡された情報をネ ットワークインタフェイスポードに出力し たり , ネットワークインタフェイスポード からの情報を NET3.COM に渡す機能を持ち ます。 それに対して NET3.COM は , ューザから り・えられた処理内容がネットワークを対象 としたものて、あるか , あるいはローカルデ イスクを対象としたものて、あるかを判断し ます。もし , ネットワークを対象としたも のて、あれば , 処理内容を IPX.COM に引き渡 します。ローカルディスクを対象としたも のて、あれば処理内容を COMMAND.COM に 引き渡します。 Net Ⅵ rare のシェルには以下の 3 種類があり ます。 ① NET3.COM EMS , XMS 環境を持っていない場合に使 用。メインメモリに約 80K バイト常駐 ② EMNET3. EXE EMS 環境を持っている場合に使用する。 メインメモリに約 20K バイト常駐 ③ XMNET3. EXE XMS 環境を持っている場合に使用。メイ ンメモリに約 20K バイト常駐 通常のアプリケーションを動かすには , やはり EMS 環境て、 EMNET3. EXE を使うの が理想的て、す (Fig. 10 ) 。 次に , バインダリオプジェクト ID を調べ ます。バインダリオプジェクトはさまざま なタイプを持っています。たとえばユーザ , ファイルサーバ , プリントサーバなどて、す。 今回の解説はユーザの ID に限定しているた め , バインダリオプジェクトタイプはユー ザとしてバインダリ ID を調べます。バイン ダリオプジェクト ID は 8 桁の 16 進数て、管理さ れています。 バインダリオプジェクト ID の値からユー ザのフルネームを調べます。プロバティの 属性はいくつかありますが , オプジェクト のフルネーム (IDENTIFICATION) として プロバティの値を調べます。さらに , ユー ザがどのグループに属しているかを調べる わけて、すが , 今度は所属しているグループ (GROUPS I'M (N) として所属しているグ ループのグループ ID を取得します。この ID の値によりバインダリネームを調べます。 所属しているグループは複数に渡っている 場合もあるのて、 , 次々に調べ , グループ ID を検出て、きなくなったら終了します (Fig. 11)0 プログラムは大きく以ドのように流れて いきます。 ①シェルのバーションの取得 ②バインダリオプジェクトの ID の取得 ③オプジェクト名からプロバティのフルネ ームを取得 ④オプジェクト名から所属しているグルー プ ID を調べ , グループ ID からグループ名 を取得 シェルのバーヨンの取得 GetNetWareSheIIVersion 関数 シェルの / ヾージョンの取得 Fig. 11 バインダリテータベース オプジェクト プロノヾティ プロノヾティ の値 名前 : TANAKA タイプ : USER : 80000002 名前 :IDENTIFICATION タイプ : アイテム 、、 TANAKA ℃ H 旧 0 ″ NetWare のシェルのバーションを調べま す。バージョンは三つの情報によって管理 されています。 メぐノヤーノヾーヾノョン nver. exe コマンドを実行下のシェルのノヾー ションて、の Ver. 3. xx の 3 がこのメジャーノヾ ージョンとなります。 マイナーノヾージョン nver. exe コマンドを実行下のシェルのノヾー ジョンて、の Ver. x. 01 の 01 がこのマイナーノヾ ージョンとなります。 レビジョン 通常このレビジョン番号については表示 されることはありません。 バインダリオジェクトの ID の取得 GetBinderyObjectID 関数 バインダリオプジェクトの取得 コマンドライ、ン引数として与えられたオ プジェクト名の ID を調べます。この場合 , オプジェクトは必ずューザて、あることを条 こて、バインダリ 件に関数を実行します。 のオプジェクトタイプを変えることにより 名前 : GROUPS 」 'M 」 N 特集 LAN プログラミング入門 61 日 GYO の EVERONE の タイプ : セット

6. 月刊 C MAGAZINE 1991年8月号

特集を△当プログラミンク入門 用しなくてはなりません。 MS ー DOS と同じレベルのファイルサービ スとしては , 読み出し専用フラグの設定な どがありますが , NetWare のファイルサー ビスとしては所有者 , ファイルの作成日 , ファイルの最新更新者 , ファイルの最新史 新日などがあげられます。 MS ー DOS のファンクションコールて、は , MS-DOS として提供される情報しか得るこ とがて、きません。したがって , 所有者など の情報は得られないわけて、す。ファイルの フラグの属性などについても同様に , ファ lSt 21 : { ンクションコールて、は MS-DOS として用意 されている部分のフラグのみが変更可能て , NetWare として用意されている細かい設定 はて、きません。 プログラム netd ⅳ . c List 3 ) NetWare が標準て、サポートする ndir. exe をまねて作ったプログラムて、す。 ndir. exe て、 はさまざまなオプションが指定て、きてソー トなどもて、きますが , 本プログラムはディ レクトリを一覧するだけの機能しか持って カレントティレクトリの情報を表示する ( netdir. c ) 9 : # i nc 1 ude 8 : #include く string. h> 7 : # i nc lude 6 : # i nc 1 ude 5 : #include く ntt. h 〉 4 : #include く nit. h 〉 3 : #include く stdio. h> 2 : # i nc lude く d i r. h> 1 : #include く dos. h 〉 く conio. h 〉 く process. h> く n iterror. h> 11 : BYTE GetCurrentDrive( void ) : 12 : void GetEntryPath ( void * , char * ) : 13 : void Get0bjectName( long, char * ) : 14 : void ShowAttributes ( LONG ) : 15 : void Fi IeNameSpI it ( char * , char * , 20 : main( void ) VOid 17 : int V3 : Char * 19 : 22 : 23 : 24 : 25 : 26 : 28 : 29 : 30 : 31 : 32 : 33 : 34 : 35 : 36 : 38 : 39 : 40 : 42 : 43 : 44 : 45 : 46 : 49 : 50 : 51 : 52 : 54 : 55 : 56 : 57 : 58 : 59 : 60 : WORD BYTE BYTE BYTE static WORD connectionlD; driveNumber; s tatus : d i rectoryHandI e : / * 接続Ⅲ * / / * カレントドライプ番号 * / / * ドライプステータス * / / * ディレクトリハンドル * / char voIumeName [ 16 ] : / * ポリューム名 * / totalBlocks, sectorsPerBlock, availableBlocks, t0taIDirectoryS10ts, availableDirectoryS10ts, volumeIsRemovabIe; stat ic char directoryPath [ 255 ] : / * ディレクトリバス * / し ONG sequence; static NWDIR_ENTRY dentry; static NWFILE-ENTRY fentry; static char pathname[13] : int compIetionCode; static char owner[48] : static char modifier[48] : static char name[IO] : static char ext[5] : / * ドライプ情報を取得 * / driveNumber ニ GetCurrentDrive ( ) : / * カレントドライプ番号の取得 * / / * スキャンのためのシーケンス変数 * / / * ディレクトリエントリ構造体 * / / * ファイルエントリ構造体 * / / * パス名 * / / * 工ラーコード * / / * 所有者 * / / * 最終変更者 * / / * ファイル名 * / / * 拡張子 * / status = GetDriveInformation( driveNumber, &connect ionl D, &directoryHandle) : if ( directoryHandle = 0 ) { fprintf(stderr, "GetDriveInformation ネットワークドライプでは exit(l); / * ディレクトリのパスを取得 * / ありません Yn") : couletianC0de = GetDirectQryPatb ( dir. 理 LQ 面 1 巳山 r 加ロ pa 山 ) : i f ( compIetionC0de ! ニ SUCCESSFUL ) { fprintf(stderr, "GetDirectoryPath ディレクトリバスを得られません exit(l); \ n 工ラーコード : %02XYn", completionCode ) : / * ディレクトリのパスの表示 * / printf("Yn ディレクトリのパス : %sYnYn", directoryPath) : / * ポリューム情報をディレクトリハンドルから取得 * / compIetionC0de ニ GetVOIumeInf0WithHandle(directoryHandle, VO ー umeName, いません。 まず , ドライプの情報を取得するためカ レントドライプのドライプ番号を調べます。 これは MS-DOS のファンクションコールに よる標準ライプラリて、ドライプ番号を取得 します。ドライプ情報を調べると , ディレ クトリハンドルと接続 ID がわかります。 次にディレクトリハンドルからポリュー ム情報を取得します。ポリューム情報から はポリューム名やサイズがわかります。 NetWare の API て、はディレクトリサーチ とファイルサーチは別の関数として提供さ れているため , まずディレクトリをサーチ し , その後て、ファイルをサーチします。 プログラムは大きく以下のように流れて いきます。 ①ドライプ情報の取得 ・カレントドライプ番号の取得 ・ディレクトリバスの取得 ・ポリューム情報をディレクトリハンド ルから取得 ②ディレクトリ情報の取得 ③ファイル情報の取得 NetWare のディレクトリを端末から見た 場合 , その内容はただの大容量ハードディ スクにしか見えません。 map コマンドて、フ ァイルサーバをドライ IF : やドライフ℃ : などと設定することにより , あたかも自分 ードディスクが増設されたよ のマシンにノ、 うな感覚て、使うことがて、きます。それ以外 のサーバへのアクセスの方法としてはサー バ名とポリューム名を直接指定する方法が あります。 これによりファイルサーバ FS ー 1 の内容 DIR F : MAP G : = FS-I/VOLI : VOLI をドライ 7G : に設定する場合 例 : ファイルサーバ FS ー 1 のポリューム MAP F : = FS-I/SYS : をドライ 7*F : に設定する場合 例 : ファイルサーバ FS ー 1 のポリューム SYS 特集 LAN プログラミング入門 65 これは直接ファイルサーバを指定する方 DIR FS-I/SYS : を見ることがてきます。

7. 月刊 C MAGAZINE 1991年8月号

史を行うにはどうすればよいて、しようか ? 答えは簡単て、す。 Fig. 2 , Fig. 3 を見れば わかるように , 親プロセスの環境変数領域 を操作すればよいわけて、す。 スタートアップルーチンて、コヒ。ーされる 環境変数のコヒ。ーや自プロセスの環境変数 領域を操作してもプログラムが終了すれば , それらの領域は解放されます。したがって , 終「後も解放されない親プロセスの環境変 数領域を操作すればよいのて、す。 言葉て、いえば非常に簡単なことて、すが , 実際に行うにはけっこうたいへんて、す。 C 言語のライプラリはスタートアップルーチ ンて、コヒ。ーされる環境変数のコヒ。ーを操作 するものばかりて、す。つまり必要とする関 数をすべて自作しなければいけません。 親プロセスの取得法 親プロセスの環境変数領域を操作するに は , まず , 親プロセスの位置を知る必要が あります。これは非常に簡単て、す。 PSP 領 域 (Table 1) の [ 16h ~ 17h ] が親プロセスの PSP セグメントを指し示しています。 MS- C, Turbo C, LSI C て、は外部変数 psp が自 プロセスの PSP セグメントを保持していま す。よって , * (unsigned fa 「 * )MK FP(_psp, 0X16 ) : により親プロセス ( 通常は COMMAND. COM) の PSP セグメントを取得することカイ きます。ただし MS ー C て、は MK FP は定義さ れていません。 Fig. 4 のように定義します。 親プロセスの 環境変数領域の取得法 Fig. 2 を見れば , 親プロセスの環境変数領 域は親プロセスの PSP セグメントの [ 2Ch ~ 2 Dh] を参照すればよいと思われるて、しょ う。確かに , 基本的にはこの方法て、親プロ セスの環境変数領域を取得することが可能 てす。しかし , 最初に起動される COM 90 C MAGAZINE 1991 MAND.COM ( 以後ルートの COMMAND. 8 COM と呼ぶ ) て、は PSP 領域の C2Ch—2Dh] が設定されていなかったり , MS-DOS のバ ージョンによっては親プロセスの PSP 領域 の C2Ch—2Dh] がダミーの環境変数領域を 指しているものもあります。それて、はどう するのか ? 親プロセスの環境変数領域の 取得法を簡単に説明します。 ルートの COMMAND.COM の環境変数領域 MS ー DOS 起動直後の状態て、は , 起動する プログラムの親プロセスはルートの COM Fig. 4 MS-C における MK—FP 定義 MAND.COM になります ( ルートの COM MAND.COM は割り込みべクタ 2Eh ( Table 2 ) が指し示しています ) 。ルートの COM MAND.COM 環境変数領域て、は Fig. 5 に示 すように , 親プロセスの PSP セグメントの [2Ch—2Dh] は通常 0000h となっています (MCB に関しては Fig. 6 を参照 ) 。したがっ て , 、 DOS ファンクション 52h(Table 3 ) て取 得て、きる先頭の MCB のセグメントアドレス から , MCB のチェーンをたどることによ り , OWNER ID がルートの COMMAND. COM と同じメモリプロックてルートの COM # define MK—FP(), 0 ) ((void far* ) (((unsigned long) (s) くく 16)l(unsigned) ( 0 ) ) ) TabIe 2 コマンドの起動 ( DOS 非公開 ) 引数 返り値 機能 INT 2Eh システムコール DS:SI コマンド文字列 INT 2Eh AL= リターンコード DS:SI が示す文字列 ( 下図参照 ) をそのまま常駐している COMMAND.COM に渡してコ マンドを起動する。戻ってきたときには CS レジスタ以外はすべて破壊されている。この 割り込みは多重コール (INT 2Eh で起動したコマンドで爪 T 2Eh を使用すること ) を行 うと , 先に起動した爪 T 2Eh を使用したプログラムが常駐してしまう DS : ↓ コマンドライン文字列 CR を除く文字数 ( 1 バイト ) ↑ CR Fig. 5 このシステムコールで SET コマンドを起動すると , 簡単に環境変数が設定 / 削除できる。 ただし , バッチファイルの中でこのシステムコールを使用したコマンドを使うと予期し ない動作を行うことがある。注意が必要である ルートの COMMAND.COM の環境変数領域 0 : 00B8 ロ (INT2Eh 割り込みべクタのセグメントアドレス ) 低位アドレス ↑・ 0 1 2 3 4 CB M SP SlZm PSPm [2Cト2Dhト0000h ルート .COM/AND.COM の PSP ルートの COMMAND.COM MCBn M PSPm SIZn ルートの COMMAND.COM の環境変数領域 高位アドレス

8. 月刊 C MAGAZINE 1991年8月号

特集生△認プログラミンク入門 ス API を使うことにより直接プリントキュー を設定て、き , ネットワーク上のプリンタに 出力て、きます。 プログラム中て、使用しているプリンタキ ューの名前は、、 PRIN TQ 0 〃と固定してい るのて、 , 実際にプログラムを動かす場合に は、、 PRINTQ 0 〃というプリンタキューを 作るか , 、、 PRINTQ 0 〃の部分を書き換えて から再コンパイルしてください プログラムは大きく次のように流れてい きます ①現在のキャプチャーフラグの値の取得 ②フラグの値をセット ③キャプチャーフラグをセット ④現在のローカルプリンタの ID を取得 ⑤プリンタキューの ID を取得 ⑥サーバへの接続番号の取得 ⑦キャプチャーのセット ⑧キャプチャーの起動 ⑨ファイルをプリンタにリダイレクション て、出力 トしています。 このプログラムて、は印刷部数を 2 部にセッ フラグの値をセット 参照 ) を使用します。 理するための構造体 ( List 5 および Table 5 の内容を読み込む際に , キャプチャーを処 この関数は現在のキャプチャーのフラグ があります。 プログラムの最後て、最初の状態に戻す必要 め , ますキャプチャーの状態を調べておき , プチャーを終了させるようになっているた セットして印刷が終了したら自動的にキャ このプログラムは勝手にキャプチャーを 取得 キャプチャーフラグのデフォルト値を GetDefauItCaptureFlags 関数 値の取得 現在のキャプチャーフラグの ⑩デフォルトのキャプチャーの値に戻す ⑩キャプチャーを終了させる キャプチャ ラグをセット SetDefaultCaptureFlags 関数 ー一変更したフラグの内容をキャプチャー にセット キャプチャーフラグの内容をキャプチャ ーにセットするためには List 6 に示す構造体 を使用します。 構造体そのものの構造は CAPTURE FLAGS とほとんど同じて、すが , formName キャプチャーを処理する構造体 lSt typedef struct { 以降のフラグについては設定不可能となっ ています。 現在のローカルプリンタの 番号を取得 キャプチャーとプリントキューの設定を する際にデフォルトのプリンタ番号が必要 となります。 GetDefaultLocalPrinter 関数 プリンタ ( LPT ) の番号を取得 キャプチャーコールに使われるデフォル BYTE BYTE BYTE BYTE BYTE BYTE BYTE Char BYTE BYTE int BYT E i nt int char BYTE BYTE BYTE Char Char BYTE BYTE BYTE BYTE long WORD status; flags; tabSize: / * ③ * / serverPrinter; numberOfC 叩 ies; / * ⑤ * / formType ; reserved : bannerText [ 13 ] : / * ⑦ * / reserve; local し PTDevice; / * ⑧ * / fIushCaptureOnDev iceClose; / * ⑩ * / fIushCaptureTimeoutCount; / * ⑨ * / formName[13] ; maxChars : maxLines; LPTCaptureFlag: / * ⑩ * / fiIeCaptureFIag; / * ⑩ * / timingOutFIag; far *printerSetupBuffer; / * far *printerResetBuffer; / * connect ionlDQueuePrintJob; capturelnProgress : printQueueFIag; printJobVaIid; printQueueI D; printJ0bNumber; / * ⑩ } CAPTURE_F し AGS ; キャプチャーをセットする構造体 typedef struct BYTE BYTE BYT E BYTE BYTE BYTE BYTE Char BYTE BYTE int BYTE int i nt Char BYTE status; flags; tabSi ze; serverPrinter; number0fCop i es : formType; reserved ; bannerText[13] ; reserve; localLPTDevice; fIushCaptureTimeoutCount; fIushCaptureOnDeviceClose; max し ines; maxChars; formName[13] : PAD[21] : } SET_CAPTURE_F し AGS; 特集 LAN プログラミング入門 71

9. 月刊 C MAGAZINE 1991年8月号

特集△認プログラミンク入門 List 3 と接åID を返します。ステータスパイト は , あるドライプがローカルドライプかネ ットワークドライプのいすれか , またはま ったくマップされていないかを返します。 ステータスパイトはディレクトリハンドル とネットワークドライプが永久的または一 時的に割り当てられているかどうかを知ら せます。 driveNumber 変数にすて、にドライ プ番号が格納されているのて、 , これを元に ドライプ情報を取得します。 バへの接続番号とディレクトリハンドルを 取得します。 バへの接続 ID は , サーバがログイン したユーザを管理す際に用いる番号て、 , 以後サーバのサービスを受ける際にはほと んどの関数て、この接続 ID を使用します。 ディレクトリハンドルは , ディレクトリ をサーチするためのポインタテープルて、す。 ファイルサーバはログインしている各端末 のディレクトリハンドルテープルを維持し ています。 このディレクトリハンドルテープルには 255 のエントリがあり , それぞれがポリュー ムやディレクトリバスをポイントするよう に設定て、きます。端末がディレクトリハン ドルをアロケートすると , そのファイルサ ーバはリクエストを出している端末のディ レクトリハンドルテープルに指定したディ レクトリのボリューム番号とディレクトリ 番号を入れます。 次にこの端末上て、稼働しているアプリケ ーションは , ディレクトリハンドルテーフ ルのインデックスて、あるディレクトリハン ドルを使ってディレクトリへ参照すること がて、きます。 GetDirectoryPath 関数 ディレクトリバスの取得 ディレクトリハンドルがわかったのて、こ の値からディレクトリバスと取得します。 このとき取得するディレクトリバスは次の ようになります。 ポリューム名 / ディレクトリ名 \ ディレクトリ名・ 例 ) sys/public 150 : 151 : 152 : 153 : 154 : 155 : 156 : 157 : 158 : 159 : 160 : 161 : 162 : 163 : 164 : } 165 : 166 : / * ドライプ番号を取得する * / 167 : BYTE 168 : GetCurrentDrive(void) 169 : { / * ドライプ番号 * / 170 : BYTE nwdrive; 171 : nwdrive ニ getdisk ( ) : 172 : return ( nwdrive ) ; 173 : 174 : 175 : 176 : VOid 177 : GetEntryPath (void *entry, char *path) 178 : NWDIR_ENTRY *dentry ま entry; 179 : 180 : strncpy(path, dentry->name, dentry->name し ength) : 181 : path[dentry->nameLength] 182 : 183 : } 184 : 185 : / * オプジェクト名を調べる。オプジェクト名がない場合は " Unknown " とする * / 186 : VOid 187 : Get0bjectName (long id, char *name) 188 : 189 : WORD type; 190 : int complet ionCode; 191 : &type) ; compIetionC0de ニ GetBinderyObjectName(id, 192 : name, if (completionC0de ! ニ 0 ) { 193 : strcpy (name, "Unknown") : 194 : 195 : 196 : } 197 : 198 : / * ファイル名を分解する * / VOid 199 : F ⅱ eNameSp ⅱ t ( char *path, char *name , char *ext ) 200 : 201 : { char drive[ MAXDRIVE ] , dir[ MAXDIR ] : 202 : 203 : fnsplit( path, drive, dir, name, ext ) : 204 : 205 : } 206 : 207 : / * ファイルの属性を表示する * / 208 : VOid 209 : ShowAttr i butes ( し ONG attr i butes) 210 : struct fileattlibute { 211 : value; 212 : long 213 : char *On; *off; 214 : Char 215 : 216 : 217 : 218 : 219 : 220 : 221 : 222 : 223 : 224 : 225 : 226 : 227 : 228 : 229 : 230 : 231 : 232 : 233 : 234 : 235 : 236 : 237 : } 5 ) & 0X000f , fentry. creationDate & 0X001f ) : / * 属性の表示 * / ShowAttr ibutes (fentry. attributes) : (fentry. modifYTime & 0X001f ) * 2 ) ; / * 所有者の表示 * / Get0bjectName (fentry. ownerID, owner) : printf("%-9s " owner) : / * 最終変更者の表示 * / Get0bjectName (fentry.IastModifierID, modifier) : printf("%-9sYn", modifier ) : } while (l); struct fi leattlibute fa[] FA READ_ONLY, FA_SHAREABLE, FA_NEEDS_ARCHIVED, FA HIDDEN, { FA_-SYSTEM, int i; printf( " for (i = 0 : i く 5 : i + + ) { if ( attributes & fa[i]. value ) printf("%s", fa[i]. on ) ; else { printf("%s", fa[i]. 0ff ) : printf( " ] 67 特集 LAN プログラミング入門

10. 月刊 C MAGAZINE 1991年8月号

ファイルサーバやプリントサーバの ID など を得ることがて、きます (TabIe 2 参照 ) 。 オプジェクト名から ブ目ノ。ティフルネーム List サーバに登録されているユーサの情報を取得 (finger. c) 1 : #include く stdio. h> 2 : #include く string. h> 3 : #include く process. h> 4 : #include く nit. h> 5 : #include く niterror. h> 6 : 7 : unsigned char identification[128]; 8 : long groupIDs[128/sizeof(Iong) ] : 9 : char groupName[48] : i nt 12 : main ( int argc, char *argv[] ) 、 / * シェルのバージョン * / 14 : BYTE maJor, mnor, reVISIon, / * ューザのオプジェクト名 * / 15 : Char *user; / * ューザのオプジェク bID * / long objectID; / * プロバティフラグ * / BYTE more, f lag; WORD / * オプジェクトタイプ * / Obj ectType : i nt comp let i onCode : / * 工ラーコード * / 20 : int i; / * コマンドライン引数がなければェラーとして終了する * / 22 : if (argc ! ニ 2 ) { 23 : fprintf(stderr, ” Usage: finger userh") : 24 : exit(l): 25 : 26 : user ニ argv[l] : strupr(user) : / * オプジェクト名を大文字に変換する * / 28 : 29 : / * NetWare のシェルバージョンを調べる * / 30 : completionCode = GetNetWareShellVers ion (&major, &minor, &revision) : if ( compIetionC0de ! = 0xFF ) { 32 : fprintf(stderr, "NetWare のシェルがロードされていません Yn 工ラーコード 33 : 34 : exit(l); 35 : = % 02X " を completionC0de) : 36 : 37 : 38 : 40 : 42 : 43 : 44 : 45 : 46 : 47 : 48 : 49 : 50 : 51 : 52 : 53 : 54 : 55 : 56 : 57 : 58 : 59 : 60 : 62 : 63 : 64 : 65 : 66 : 67 : 68 : 69 : 70 : 71 : 73 : 74 : 75 : 77 : 79 : 80 : 83 : 84 : 85 : ReadPropertyValue 関数 プロバティのフルネームを取得 プロバティの名前を取得します。 こて、 は、、 IDENTIFICATION" ( オプジェクトの フルネーム ) としてプロバティを調べます。 、、 IDENTIFICATION" 以外にもいくつか のプロバティがあります。 GROUP MEMBERS プロバティ ューザグループのメンバて、あるユーサの リストが含まれます。このプロバティはユ ーザグルーブオプジェクトにつきます。 GROUPS I'M 爪プロバティ ユーザがメンノヾて、あるユーザグループの リストが含まれます。このプロバティはユ ーザまたはユーザオプジェクトにアタッチ されます。 IDENT 下℃ AT ℃ N プロノヾティ ユーザまたはユーザグループのフルネ ムが含まれます。 このプロバティはユーザ またはユーザグルーブオプジェクトにアタ ッチされます。 OPERA 引 ORS プロバティ 許可されたファイルサーバコンソールオ ペレータのオプジェクトのリストが含まれ このプロバティはファイルサーバのオプ ジェクトにアタッチされます。 PASSWORD プロバティ オプジェクトの暗号化されたパスワード が含まれます。 このプロバティはユーザオプジェクトに アタッチされます。ファイルサー ノヾ、ロクヾ インするオプジェクトは PASSWORD プロ パティが必要て、す。 SECURITY EQUALS プロバティ セキュリティ等価のオプジェクトリスト が含まれます。このプロバティはユーザと ューザグルーブオプジェクトにアタソチさ れます。 62 C MAGAZINE 1991 8 ネ酉 / ルの * フ名 のププ 一ルル ュググ / * NetWare のシェルバージョンの表示 * / printf ( " シェルバージョン : v%d. % 02d. %02dYn", maJor, minor, revision) : / * バインダリオプジェク日 D の取得 * / completionC0de = GetBinderyObjectID(user, OT-USER, &0bjectID) : if ( complet ionC0de ! = SUCCESSFUL ) { fprintf(stderr, "GetBindery0bjectID バインダリオプジェク日 D が得られ exit(l) ; ません \ n 工ラーコード : %02XYn", completionCode ) : / * オプジェク日 D の表示 * / printf( " ユーザ %s のオプジェクト ID は % ld ( % 08 以 h ) です。 Yn", user, / * フルネームの取得 * / 0bjectID, objectID ) : compIetionC0de = ReadPropertyVaIue( user, OT USER, ” IDENTIFICATION" identification. &moré, &flag) : / まフルネームの表示 * / if ( compIetionC0de ! = SUCCESSFU し ) printf ( " フルネームは登録されていせん \ n ” , identification),• else { printf(" フルネーム : %sYn" identification) : / * グループ名の取得 * / completionCode = ReadPropertyValue (user, OT_USER, "GROUPS_IY'M_IN" (BYTB * ) groupIDs, &more, &flag) : i f ( completionC0de ! = SUCCESSFU し ) { fprintf(stderr, "ReadPropertyValue(GROUPS_IY'M_IN) グループ名が exit(l); 得られません \ n 工ラーコード : %02XYn", completionCode ) : / * グループリストの表示 * / printf(" ユーザ %s が所属しているグループ : " , user); / * グループ ID が NUL しになるまでループを続ける * / for (i = 0 : groupIDsCi] い 0 し i + + ) { groupName, &0bjectType ) : / * グループ名の取得 * / co 叩 let i onC0de = GetB i ndery0bjectName ( し ongSwap ( group I Ds [ i ] ). if ( completionC0de ! = SUCCESSFU し ) { fprintf( stderr, "GetBindery0bjectName グループ名が得られません exit( 1 ) : Yn 工ラーコード : %02XYn", compIetionC0de ) : / * グループ名の表示 * / printf( "%s " groupName ) : putchar( 'Yn' ) :