2017-05-03 8 views
-2

私のIT学校では、単にグループのないコマンド "id"と同じように、ユーザーIDとユーザーグループIDを出力するプログラムを作成する必要があります。 これはうまくいきましたが、今は​​というメソッドを使って拡張バージョンを作成する必要があります: ./id_extended USERNAMEとして使用し、そのユーザーのuidとgidを出力する必要があります。私はgetpwnam(3)を見ました。レッスンではそれを見てくれと教えてくれたからです。今ではバッファなどでgetpwnam_rを使用する例がありますが、これはどうやって作成するのではありません。我々は単純な​​を使用しなければなりません。CメソッドIDとgetpwnam(3)

私は​​がポインタを返すことを知っていますが、このポインタをユーザグループIDとユーザIDにどのように使用できますか?

+2

'getpwnam'は必要なデータを持つ構造体へのポインタを返します。[man page](https://linux.die.net/man/3/getpwnam)はその構造を記述しています。もしあなたが何か問題があれば、あなたが試したことを投稿するかもしれませんか? – ilkkachu

+0

ようこそスタックオーバーフロー。まもなく、[About]と[Ask]ページをお読みください。 ['getpwnam()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwnam.html)やあなたのマシンのマニュアルページの仕様を読む必要があります。それは簡単です。構造体には必要な情報がほとんど含まれていますが、おそらくグループIDをグループ名(['getgrgid()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/)にマップする必要があります。 getgrgid.html))。 –

+0

ああ、まもなく、この問題は起こりませんでした。残念です。/ – xLeevo

答えて

0

OPに質問にそのコードが含まれているはずです。

#include <pwd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 

これはPOSIX.1のCコードであるため、コードは、たとえば、で始まる必要があります。 #define _POSIX_C_SOURCE 200809LがPOSIX.1-2008の機能を望むことをCライブラリのヘッダーファイルに伝えます。

getpwnam()は、#include <pwd.h>が必要であり、また、#include <sys/types.h>が必要です。これは記載されていません。

getuid()およびgetgid()は、リストされている#include <unistd.h>を必要とします。

標準入出力には#include <stdio.h>が必要で、#include <errno.h>にはerrnoとエラーコードがあります。私は個人的にも#include <string.h>strerror()ため、私は私自身のフォーマットでエラーメッセージを印刷するfprintf()を使用したいので(例えば<stdio.h>からperror()、または%m GNUの拡張機能を使用するのではなく。

だろう次の部分、

struct passwd *getpwnam(const char *name); 
uid_t getuid(void); 
uid_t geteuid(void); 
struct passwd pass; 

はかなり問題があります:最初に、Cライブラリ関数を宣言する必要はなく、ヘッダファイルはすでにそれらを宣言しています。 - ので、と宣言します210はゼロになります。第3に、passmain()でのみ使用される場合は、グローバル変数(関数外)ではなく、main()のローカル変数として宣言する必要があります。我々はmain()が正しく(int argcchar *argv[]を取ると)定義されていることがわかり、最後の部分では

int main(int argc,char* argv[]) { 
    if(argc == 1){ 
    printf("user: %d\ngroup: %d\n",getuid(),getgid()); 
    } 
    if(argc == 2){ 
    pass = getpwnam(argv[1]); 
    printf("%s %ld",pass.pw_uid,pass.pw_gid); 
    } 
} 

。しかし、宣言が要求する文はない。return (some int)。これは、末尾にreturn EXIT_SUCCESS;を追加することによって最も適切に修正されます。 passので

のみmain()で使用され、それはローカル変数でなければならず、したがってmain()の本体は、その正しい宣言で始まる必要があり:struct passwd *pass;

2つ以上の引数を指定すると、プログラムは何も行いません。それは非常に驚くべきことであり、望ましくない。あまりにも多くの引数の場合にエラーメッセージが表示されたif (argc == 1) { /* no arguments */ } else if (argc == 2) { /* one argument */ } else { /* two or more arguments */ }は、ここでもっと賢明な選択肢になります。一つの引数の場合

argc == 2からargcこのプログラムを実行するために使用される名前である、argv[0]を含むことを覚えている)2つの別個の問題がある:第一に、passを宣言することによって固定することができるポインタ(ありません上に示したように)。第二に、より重要な点は、getpwnam()が成功したか失敗したかのチェックがないことです。

エラーの場合、man 3 getpwnamは、エラーが発生した場合はNULLを返し、エラーが発生した場合はerrnoを返します。つまり、passが正しく宣言されている場合は、たとえばif (!pass)はPOSIX.1 C.

if (pass == NULL)と等価であること

pass = getpwnam(argv[1]); 
    if (!pass) { 
     fprintf(stderr, "%s: %s.\n", argv[1], strerror(errno)); 
     return EXIT_FAILURE; 
    } 

    /* pass->pw_uid has user ID, 
     pass->pw_gid has group ID, 
     pass->pw_name has user name, 
     and so on. */ 

は注意(短い形式を使用すると、!ないオペレータですので、私は実際として最初にお読みください。ちょうど私の個人的な好みです「何passがない場合は」;。。「passがNULLであれば、」私はように、第2の読み前者は/高速化/私のために、より快適なだけで簡単です)

uid_tまたはgid_tのprintf形式指定子はありません。ほとんどのコードはint%d)を使用し、コンパイラがプロモーションを正しく処理すると仮定していますが、私は個人的にlong%ld)を使用して結果をlongに明示的にキャストします。例えば、

printf("uid=%ld (%s)\n", (long)(pass->pw_uid), pass->pw_name); 

は(ほとんどの場合、あなたは(long)pass->pw_uidとして書かれたキャストを見ていますが、Cのぶっきらぼうに演算子の優先順位のルールを覚えていない限り、それは表現の一部がlongにキャストされ明らかではないかもしれません。コードを読む人間に明示的に明確にするために - コンパイラは間違いなく気にしません - 私は時々それを(long)(pass->pw_uid)と書いています。キャストアイテムは明らかに(pass->pw_uid)です。すなわち、構造内のpw_uidフィールドの値passを指す)

Fi全体として、私が提案したいプログラムロジックには2つの変更があります。

ユーザー名が指定されている場合はstruct passwd *passを使用する代わりに、ユーザー名が指定されていない場合にも使用して、getpwuid(getuid())を使用して現在のユーザー情報を取得します。次に、passが指し示す構造体に情報を出力するコードは、if (argc == ..)節の本文の外側にある可能性があります。この方法では、情報を印刷するのはprintf()の1つのみで、現在のユーザー用に印刷されているのか、名前で指定された他のユーザー用に印刷されているかにかかわらず、常に同じ形式になります。

getuid()getgid()はPOSIX.1に常に成功している。彼らは失敗することはできません、すべてのエラーは次のように確認することなく、それらを使用することは完全に大丈夫である理由がある。。)

は、第二の変化は、より多くの追加のようなものです。getgrgid(pass->pw_uid)またはgetgrgid(getgid())を使用して、ユーザーグループに関する同様の情報を提供するstruct groupへのポインターを取得することができます。特にグループの名前である->gr_nameがあります。 getgrgid()を使用するには、ファイルの先頭近くに#include <grp.h>も指定する必要があります。 (#include <sys/types.h>が必要ですが、すでにそれがある必要があります。getpwnam()getpwuid()が必要です)

上記の情報は、記載された要件に従って完全に動作するプログラムを作成するのに十分なはずです。しかし、あなたはもっと学び、あなた自身の仕事を完了することの満足を得るために、完全な修正/変更されたプログラムをリストアップするつもりはない - そして、フリーローダーが私たちの仕事を悪用するのを避けるために、自分の。

関連する問題