本文に進む 日本−日本語
日本HPホーム 製品とサービス お客様サポート/ ダウンロード ソリューション ご購入の方法
≫ お問い合わせ
詳細検索オプション
日本HPホーム
HP-UX リファレンス: セクション 3 : ライブラリ (N~Z) > r

rcmd(3N)

HP-UX 11i Version 2: September 2004
≫ 

テクニカル ドキュメント

PDF版
フィードバック
ここから本文が始まります

 ≫ 目次

 ≫ 索引

名称

rcmd(), rcmd_af(), rresvport(), rresvport_af(), ruserok() ― リモートコマンドにストリームを返す

構文

int rcmd( 
     char **ahost, 
     int remport, 
     const char *locuser, 
     const char *remuser, 
     const char *cmd, 
     int *fd2p); 
 
int rcmd_af( 
     char **ahost, 
     int remport, 
     const char *locuser, 
     const char *remuser, 
     const char *cmd, 
     int *fd2p, 
     int af); 
 
int rresvport(int *port); 
 
int rresvport_af(int *port,int af); 
 
int ruserok( 
     const char *rhost, 
     int superuser, 
     const char *ruser, 
     const char *luser); 

説明

rcmd()

rcmd() 機能は、 リモートホスト上でコマンドを実行する、特権プログラムに使用されます。 rcmd() は、 コマンドの標準入力と標準出力が接続されたソケットのファイル記述子を返します。 rcmd() に対するコマンドレベル インタフェースは、BSD rsh と同じコマンドの remsh によって提供されます remsh(1) 参照)。

ahost はリモートホスト名アドレスのポインターです。 リモートホストの名前は、公式のホスト名か、 gethostbyname() によって識別されるのであれば、エイリアスであってもかまいません gethostent(3N), named(1M), および hosts(4) 参照)。

remport は、リモートシステムのインターネットポートで、 rcmd() が接続しようとします。

locuser および remuser は、それぞれローカルホストとリモートホストのユーザーログイン名を示します。 これらのログイン名により、リモート ホストサーバーがユーザーを認証します。 (以下の ruserok() 参照)。

cmd は、リモートホストで実行すべきコマンドを指定する文字列です。

fd2p は、整数のポインターです (このポインターはヌルであることもあります)。

rcmd()gethostbyname() を使用してホスト *ahost を調べますが、ホストが存在しない場合は、-1 を返します。 ホストが存在する場合、 *ahost は、ホストの標準名にセットされ、ポート remport に常駐しているサーバーへの接続が行われます。 サーバーとの接続に 5 回以上失敗した場合、 あるいはポートが使用中ではないのに接続が行われない場合は、 rcmd() により -1 が返されます。

呼び出しが実行されると、 SOCK_STREAM タイプのソケットが呼び出し側に返され、リモートコマンドに stdin および stdout として渡されます。 fd2p がヌルでない場合、 rcmd() は呼び出しプロセス (ローカル) と制御プロセス (リモート) 間の 2 番目のソケットを オープンして、その記述子を *fd2p に入れます。 この接続では、制御プロセスが cmd から 呼び出しプロセスへ診断出力 (stderr) を送ると同時に、 cmd に転送する UNIX シグナルを呼び出しプロセスから受取ります。 予備のポートが確立できなかった場合、 rcmd() は -1 を返します。 fd2p がヌルの場合、リモートコマンドの stderr は、 stdout と同じにされ、任意のシグナルをリモートプロセスに送信するための準備はされません。

このプロトコルの詳細は、 remshd(1M) の項で説明してあります。

rcmd() を使用するプログラムはスーパーユーザーが実行しなければなりません。

rcmd_af()

rcmd_af() 関数は rcmd() と同じように動作しますが、それ以外に TCP ソケット AF_INET6 を作成することもできます。作成するソケットのタイプは、 af 引き数で指定します。 rcmd_af() は、アドレスファミリー af がサポートされていないと失敗します。 このときのエラーは EAFNOSUPPORT として報告されます。

rresvport()

rresvport() 関数はソケットを作成し、予約されたポートに結び付けます。このソケットは rcmd() および他のいくつかのルーチンで使用できるようになっています。

発信側は、 *port の初期値を 512 から IPPORT_RESERVED-1 までの数値で設定します (IPPORT_RESERVED の値は netinet/in.h で定義されており、1024 となっています)。 多くの場合、 *port の初期値は IPPORT_RESERVED-1. に設定されています。 セットされた値が有効な範囲にない場合は、 rresvport() がその値を IPPORT_RESERVED-1 に警告なくリセットします。 関数は *port の初期値を最初のポート番号として使います。 これにより、関数は作成されたソケットに 結合 します。 この操作が失敗した場合、 rresvport()*port を減らして、ソケットの新規ポート番号を 結合 します。 操作が正常終了するまで、または 512 から IPPORT_RESERVED-1 までのポート番号がなくなるまで、 プロセスが繰り返されます。

呼び出しが正常終了すると、ソケット記述子が発信側に返され、 port が指す位置にポート番号が返されます。 呼び出しが失敗の場合には、-1 が発信側に返されます。

rresvport() によって返されたソケットでは SO_KEEPALIVE オプションがオンになります。

ソケットに特権アドレスを結合できるのは、スーパーユーザーのみです。 したがって、 rresvport() を使用したプログラムは、スーパーユーザーとして実行しなければなりません。

rresvport_af()

rresvport_af() 関数は rresvport() と同じように動作しますが、それ以外に TCP ソケット AF_INET6 を作成することもできます。作成するソケットのタイプは、 af 引き数で指定します。 rresvport_af() は、アドレスファミリー af がサポートされていないと失敗します。 このときのエラーは、 EAFNOSUPPORT として報告されます。

ruserok()

ruserok() 関数は、 rcmd() を使用して、サービスを要求するクライアントをサーバーが 認証するためのものです。 ruserok()rhost 上の ruser が、ローカルホスト上で luser として振る舞うことを許されているかどうかを確認します。

superuser は整数フラグで、ローカルユーザー名がスーパーユーザーに対応していれば 0 以外になります。 superuser フラグが立てられていない場合、 ruserok() は、まずファイル /etc/hosts.equiv をチェックしてサービスが受けられるかどうか確認します。 確認できると ruserok() は 0 を返します。 superuser フラグが立てられているか、ファイル /etc/hosts.equiv が存在しないか、ユーザーチェックができなかった場合、 ruserok() は、引き続きローカルユーザーのホームディレクトリ内のファイル .rhosts を (存在すれば) 調べます。 ruserok() は、ユーザーチェックができた場合は 0 を返します。 チェックできない場合は -1 を返します。

通常、 /etc/hosts.equiv ファイルには、ホスト名のリストが格納されており、また、ユーザーの .rhosts ファイルには、ホスト名/ユーザー名の対が格納されています。 リモートユーザーは、リモートホスト名が /etc/hosts.equiv に含まれており、リモートユーザー名とローカルユーザー名が一致しているか、またはリモートホスト名とリモートユーザー名が、ローカルユーザーのホームディレクトリ内の .rhosts に対で出現する場合、 ruserok() によってチェックされます。

ruserok() が理解する構文についての、詳しい解説は、 hosts.equiv(4) を参照してください。

診断

rcmd() 診断メッセージ

rcmd() は、以下の診断メッセージを返します。

hostname: Unknown host
  

gethostbyname が、サーバーの名前と一致するエントリーを、ホストデータベースの中から見つけられなかったことを表します gethostent(3N) および hosts(4) 参照)。

対処法: ホストのシステム管理者に、リモートホストのエントリーが hosts データベースにあるかどうか調べてもらってください hosts(4) 参照)。

connect: hostname: ...
  

予約されたポートへの接続が行われないことを表します。 この診断メッセージには、接続が行われない理由を明記したメッセージが付けられます。

write: Setting up stderr
  

エラーメッセージを、送出用にセットアップされたソケット接続へ書き出す際にエラーが起きたことを表します。

system call : ...
  

システムコールを実行する際にエラーが起きたことを表します。 このメッセージには、エラーの原因を明記したメッセージが付けられます。

socket: Protocol failure in circuit setup
  

予約されたポート上で、ソケットの接続が行われなかったか、ソケットアドレスがインターネットファミリー タイプのものでなかったことを表します。

read: hostname: ...
  

標準ソケット接続から情報を読み込む際にエラーが生じたことを表します。 このメッセージには、エラーの原因を明記したメッセージが付けられます。

Connection timeout
  

エラー接続用の第 2 のソケットがセットアップされてから 30 秒以内に、リモートホストからこのソケットへの接続が行われなかったことを表します。

Lost connection  

ソケットからの読み込みを、プログラムが行えなかったことを表します。 これは、リモートホストからのソケット接続が切れたことを意味します。

message... 

デーモンからのエラーメッセージが、ソケット接続を通じて転送されることがあります。 そのメッセージは、 stderr に送られます。

primary connection shutdown
  

第 2 のソケットがセットアップされるまでの間に、 rcmd() によって、第 1 の接続がシャットダウンされたことを表します。 これは、 inetd の保護の失敗によるものかもしれません。

recv: ... 

第 2 の (stderr) ソケット接続が行われるまでの間に、第 1 の接続において rcmd() がエラー状態に陥ったことを表します。

accept: Interrupted system call
  

第 2 のソケット接続が行われるまでの間に、 rcmd() の何らかのリリースが不足して、接続がタイムアウトになったことを表します。

対処法: コマンドを繰り返してください。

rresvport() 診断メッセージ

rresvport() は次の診断メッセージを生成します。 rcmd()rresvport() を呼び出すため、メッセージは rcmd() にも送られます。

system call: ... 

システムコールを実行する際にエラーが生じたことを表します。 このメッセージには、システムコールによって返されるエラーメッセージが付けられます。

socket: All ports in use
  

予約されたポートのすべてが使用中であることを表します。 タイムアウトが生じた場合には、 インターネットサービスがインストールされているかどうか、また inetd が実行されているかどうか調べてください。

下記のように、 rcmd() を呼び出して、 リモートアカウント chm により、リモートホスト hpxzgy に対し date コマンドを実行します。 このプログラムは、スーパーユーザー特権を必要とし、リモートアカウントが、プログラムを実行するローカルアカウントと等しいことが条件となります hosts.equiv(4) 参照)。

 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netdb.h>
 #include <stdio.h>
 #include <pwd.h>
struct passwd *getpwuid();
 char *host[] = { "hpxzgy"  };
 char *cmd = "date";
 char *ruser = "chm";
main(argc,argv)
      int argc;
      char **argv;
 {
      struct servent *sp;
      struct passwd *pwd;
      FILE *fp;
      char ch;
      int rem;
      sp = getservbyname("shell","tcp");
      pwd = getpwuid(getuid());
      rem = rcmd(host, sp->s_port, pwd->pw_name, ruser, cmd, 0);
      if (rem < 0)
           exit(1);   /* rcmd が自己のエラーメッセージを出します */
      fp = fdopen(rem, "r");
      while ((ch = getc(fp)) != EOF)
           putchar(ch);
 }

警告

rcmd()socket() の呼び出しに対して行うオプションを特定する方法はありません。 rcmd() は、スタティックデータ領域内で、 (*ahost) に対するポインターを、ホストの標準名に対するポインターで置き換えてしまうので、もとの値を後から使いたい場合には、あらかじめユーザーのデータ領域にその値をコピーしておかなければなりません。 そうしないと、予想外の結果が生じます。

IPv6 は、HP-UX 11i バージョン 1.0 にオプションの IPv6 ソフトウェアをインストールすることで利用できます。HP-UX 11i バージョン 1.6 を実行するシステムでは、現在サポートされていません。

著者

rcmd() は、カリフォルニア大学バークレイ校で開発されました。

印刷用画面へ
プライバシー 本サイト利用時の合意事項
© 1983-2004 Hewlett-Packard Development Company, L.P.