私は誰?(whoami)


アニメ『私がモテてどうすんだ』
ぽっちゃり高校生の芹沼花依は、自身は小馬鹿にされつつも、男同士が仲良くしているのを見てBL妄想する腐女子。アニメの大好きキャラが死んだショックを受け部屋にこもって学校を休み続け、ようやく復活して自分の顔を鏡で見ると、なんとそこには美少女が。
普段小馬鹿にしていたクラスの男子の目も美少女を見る目に変わって、とりわけ美少年たちからは、熱烈アプローチを受けるようになります。

普通に生活してたら、鏡に映ってるのが誰か分からないなんてないですよね。まあ、鏡を初めて見たとか、記憶喪失とか、寝てる間に特殊メイクを施されたとかですかね。今回はあまり使った経験のないコマンドwhoamiです。

使い方はwhoamiと入力するだけ。

takk@deb83:~$ whoami
takk
takk@deb83:~$ 

ユーザ名が表示されました。
どんなプログラムか気になります。予め/usr/src下に格納してあるcoreutilsのソースを見てみます。
まずは行数。

takk@deb83:/usr/src/coreutils/src$ wc -l whoami.c
94 whoami.c
takk@deb83:/usr/src/coreutils/src$ 

行数が少ないので全文見てみましょう。

takk@deb83:/usr/src/coreutils/src$ cat -n whoami.c
     1	/* whoami -- print effective userid
     2	
     3	   Copyright (C) 1989-2014 Free Software Foundation, Inc.
     4	
     5	   This program is free software: you can redistribute it and/or modify
     6	   it under the terms of the GNU General Public License as published by
     7	   the Free Software Foundation, either version 3 of the License, or
     8	   (at your option) any later version.
     9	
    10	   This program is distributed in the hope that it will be useful,
    11	   but WITHOUT ANY WARRANTY; without even the implied warranty of
    12	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13	   GNU General Public License for more details.
    14	
    15	   You should have received a copy of the GNU General Public License
    16	   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
    17	
    18	/* Equivalent to 'id -un'. */
    19	/* Written by Richard Mlynarik. */
    20	
    21	#include <config.h>
    22	#include <stdio.h>
    23	#include <sys/types.h>
    24	#include <pwd.h>
    25	#include <getopt.h>
    26	
    27	#include "system.h"
    28	#include "error.h"
    29	#include "long-options.h"
    30	#include "quote.h"
    31	
    32	/* The official name of this program (e.g., no 'g' prefix).  */
    33	#define PROGRAM_NAME "whoami"
    34	
    35	#define AUTHORS proper_name ("Richard Mlynarik")
    36	
    37	void
    38	usage (int status)
    39	{
    40	  if (status != EXIT_SUCCESS)
    41	    emit_try_help ();
    42	  else
    43	    {
    44	      printf (_("Usage: %s [OPTION]...\n"), program_name);
    45	      fputs (_("\
    46	Print the user name associated with the current effective user ID.\n\
    47	Same as id -un.\n\
    48	\n\
    49	"), stdout);
    50	      fputs (HELP_OPTION_DESCRIPTION, stdout);
    51	      fputs (VERSION_OPTION_DESCRIPTION, stdout);
    52	      emit_ancillary_info ();
    53	    }
    54	  exit (status);
    55	}
    56	
    57	int
    58	main (int argc, char **argv)
    59	{
    60	  struct passwd *pw;
    61	  uid_t uid;
    62	  uid_t NO_UID = -1;
    63	
    64	  initialize_main (&argc, &argv);
    65	  set_program_name (argv[0]);
    66	  setlocale (LC_ALL, "");
    67	  bindtextdomain (PACKAGE, LOCALEDIR);
    68	  textdomain (PACKAGE);
    69	
    70	  atexit (close_stdout);
    71	
    72	  parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
    73	                      usage, AUTHORS, (char const *) NULL);
    74	  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
    75	    usage (EXIT_FAILURE);
    76	
    77	  if (optind != argc)
    78	    {
    79	      error (0, 0, _("extra operand %s"), quote (argv[optind]));
    80	      usage (EXIT_FAILURE);
    81	    }
    82	
    83	  errno = 0;
    84	  uid = geteuid ();
    85	  pw = (uid == NO_UID && errno ? NULL : getpwuid (uid));
    86	  if (pw)
    87	    {
    88	      puts (pw->pw_name);
    89	      exit (EXIT_SUCCESS);
    90	    }
    91	  fprintf (stderr, _("%s: cannot find name for user ID %lu\n"),
    92	           program_name, (unsigned long int) uid);
    93	  exit (EXIT_FAILURE);
    94	}

whoamiの結果を表示するための処理は、84行目からですね。
geteuid()を取得して、さらにgetpwuidを取得しています。
それぞれどんな関数なんでしょうか。manコマンドの出番です。

takk@deb83:~$ man geteuid
GETUID(2)                  Linux Programmer's Manual                 GETUID(2)



名前
       getuid, geteuid - ユーザー ID を得る

書式
       #include <unistd.h>
       #include <sys/types.h>

       uid_t getuid(void);
       uid_t geteuid(void);

説明
       getuid()  は呼び出し元のプロセスの実ユーザー ID を返す。

       geteuid()  は呼び出し元のプロセスの実効ユーザー ID を返す。

エラー
       これらの関数は常に成功する。

準拠
geteuid(2):
GETPWNAM(3)                Linux Programmer's Manual               GETPWNAM(3)



名前
       getpwnam, getpwnam_r, getpwuid, getpwuid_r - パスワードファイルのエント
       リの取得

書式
       #include <sys/types.h>
       #include <pwd.h>

       struct passwd *getpwnam(const char *name);

       struct passwd *getpwuid(uid_t uid);

       int getpwnam_r(const char *name, struct passwd *pwd,
                   char *buf, size_t buflen, struct passwd **result);

       int getpwuid_r(uid_t uid, struct passwd *pwd,
                   char *buf, size_t buflen, struct passwd **result);

   glibc 向けの機能検査マクロの要件 (feature_test_macros(7)  参照):
getpwuid(3):

さらにmanを読んで行くと、getpwuidで得られる構造体の解説もあります。

       passwd 構造体は、<pwd.h> で以下のように定義されている:

           struct passwd {
               char   *pw_name;       /* ユーザ名 */
               char   *pw_passwd;     /* ユーザのパスワード */
               uid_t   pw_uid;        /* ユーザ ID */
               gid_t   pw_gid;        /* グループ ID */
               char   *pw_gecos;      /* ユーザ情報 */
               char   *pw_dir;        /* ホームディレクトリ */
               char   *pw_shell;      /* シェルプログラム */
           };

では、whoamiを自作してみましょう。whoismeです。

takk@deb83:~$ cat -n whoisme.c
     1	#include <stdio.h>
     2	#include <pwd.h>
     3	
     4	#include <stdlib.h>
     5	#include <time.h>
     6	
     7	int main()
     8	{
     9	        srand(time(NULL));
    10	
    11		if( rand() % 10 ){
    12			puts("I don't know.");
    13		}else{
    14			struct passwd *pw = getpwuid(geteuid());
    15			puts(pw->pw_name);
    16		}
    17	}
takk@deb83:~$ gcc -o whoisme whoisme.c

who is me?なんて聞くと、時々答えてくれます。

takk@deb83:~$ ./whoisme
I don't know.
takk@deb83:~$ ./whoisme
I don't know.
takk@deb83:~$ ./whoisme
I don't know.
takk@deb83:~$ ./whoisme
I don't know.
takk@deb83:~$ ./whoisme
I don't know.
takk@deb83:~$ ./whoisme
I don't know.
takk@deb83:~$ ./whoisme
I don't know.
takk@deb83:~$ ./whoisme
takk
takk@deb83:~$ 

コメント

タイトルとURLをコピーしました