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に、pass
がmain()
でのみ使用される場合は、グローバル変数(関数外)ではなく、main()
のローカル変数として宣言する必要があります。我々はmain()
が正しく(int argc
とchar *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()
が必要です)
上記の情報は、記載された要件に従って完全に動作するプログラムを作成するのに十分なはずです。しかし、あなたはもっと学び、あなた自身の仕事を完了することの満足を得るために、完全な修正/変更されたプログラムをリストアップするつもりはない - そして、フリーローダーが私たちの仕事を悪用するのを避けるために、自分の。
'getpwnam'は必要なデータを持つ構造体へのポインタを返します。[man page](https://linux.die.net/man/3/getpwnam)はその構造を記述しています。もしあなたが何か問題があれば、あなたが試したことを投稿するかもしれませんか? – ilkkachu
ようこそスタックオーバーフロー。まもなく、[About]と[Ask]ページをお読みください。 ['getpwnam()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwnam.html)やあなたのマシンのマニュアルページの仕様を読む必要があります。それは簡単です。構造体には必要な情報がほとんど含まれていますが、おそらくグループIDをグループ名(['getgrgid()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/)にマップする必要があります。 getgrgid.html))。 –
ああ、まもなく、この問題は起こりませんでした。残念です。/ – xLeevo