trueとfalseは表裏一体


アニメ『この素晴らしい世界に祝福を!2』
コメディが見てて楽でいいです。誰も死なないしハラハラドキドキないですからね。一話で「サトウ カズマ」の裁判が行われます。嘘をつくと、嘘発見器がチーンと鳴ります。
嘘でも本当でも、彼はどっちみち有罪にされそうです。

最近までtrueとfalseコマンドの存在を知りませんでした。何をするコマンドなんでしょうか。man trueで確認してみます。

名前
       true - 何もせず、成功で終了する

書式
       true [コマンドライン引数は無視されます]
       true OPTION

説明
       終了コードは成功になります。

       --help この使い方を表示して終了する

       --version
              バージョン情報を表示して終了する

       注意:  使用しているシェルによっては組み込みコマンドとして true を持って
       いる場合 があり、通常はここで記述しているバージョンより優先的に使用され
       ます。シェルの 文書を参照してオプションなどの詳細を確認してください。

true(1):

何もせず成功で終了する。。。使ってみましょう。

takk@deb83:~$ true
takk@deb83:~$ 

やはり何もしませんでした。trueは成功(0)が返るのか確認してみます。

takk@deb83:~$ true;echo $?
0
takk@deb83:~$ 

falseも見てみましょう。

takk@deb83:~$ false;echo $?
1
takk@deb83:~$ 

trueは0、falseは1が返りました。この2つのコマンド、ただそれだけなのでしょうか。

次はソースを見てみます。

coreutilsパッケージにあります。

takk@deb83:~$ apt-get source coreutils

trueコマンドから。

takk@deb83:~$ cat -n coreutil-4.4/src/true.c
     1	/* Exit with a status code indicating success.
     2	   Copyright (C) 1999-2014 Free Software Foundation, Inc.
     3	
     4	   This program is free software: you can redistribute it and/or modify
     5	   it under the terms of the GNU General Public License as published by
     6	   the Free Software Foundation, either version 3 of the License, or
     7	   (at your option) any later version.
     8	
     9	   This program is distributed in the hope that it will be useful,
    10	   but WITHOUT ANY WARRANTY; without even the implied warranty of
    11	   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12	   GNU General Public License for more details.
    13	
    14	   You should have received a copy of the GNU General Public License
    15	   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
    16	
    17	#include <config.h>
    18	#include <stdio.h>
    19	#include <sys/types.h>
    20	#include "system.h"
    21	
    22	/* Act like "true" by default; false.c overrides this.  */
    23	#ifndef EXIT_STATUS
    24	# define EXIT_STATUS EXIT_SUCCESS
    25	#endif
    26	
    27	#if EXIT_STATUS == EXIT_SUCCESS
    28	# define PROGRAM_NAME "true"
    29	#else
    30	# define PROGRAM_NAME "false"
    31	#endif
    32	
    33	#define AUTHORS proper_name ("Jim Meyering")
    34	
    35	void
    36	usage (int status)
    37	{
    38	  printf (_("\
    39	Usage: %s [ignored command line arguments]\n\
    40	  or:  %s OPTION\n\
    41	"),
    42	          program_name, program_name);
    43	  printf ("%s\n\n",
    44	          _(EXIT_STATUS == EXIT_SUCCESS
    45	            ? N_("Exit with a status code indicating success.")
    46	            : N_("Exit with a status code indicating failure.")));
    47	  fputs (HELP_OPTION_DESCRIPTION, stdout);
    48	  fputs (VERSION_OPTION_DESCRIPTION, stdout);
    49	  printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
    50	  emit_ancillary_info ();
    51	  exit (status);
    52	}
    53	
    54	int
    55	main (int argc, char **argv)
    56	{
    57	  /* Recognize --help or --version only if it's the only command-line
    58	     argument.  */
    59	  if (argc == 2)
    60	    {
    61	      initialize_main (&argc, &argv);
    62	      set_program_name (argv[0]);
    63	      setlocale (LC_ALL, "");
    64	      bindtextdomain (PACKAGE, LOCALEDIR);
    65	      textdomain (PACKAGE);
    66	
    67	      /* Note true(1) will return EXIT_FAILURE in the
    68	         edge case where writes fail with GNU specific options.  */
    69	      atexit (close_stdout);
    70	
    71	      if (STREQ (argv[1], "--help"))
    72	        usage (EXIT_STATUS);
    73	
    74	      if (STREQ (argv[1], "--version"))
    75	        version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version, AUTHORS,
    76	                     (char *) NULL);
    77	    }
    78	
    79	  exit (EXIT_STATUS);
    80	}

59〜77は、引数がある時の処理なので、このコマンドのメイン処理としては、79行目のexit呼び出ししかありません。
EXIT_STATUSが0なんでしょうか。

EXIT_STATUSが定義されていなければ、24行目でEXIT_SUCCESSとなり、さらに27行目の#ifで、
プログラム名が”true”になります。
あれ、プログラム名がfalseの場合もあります。

    23	#ifndef EXIT_STATUS
    24	# define EXIT_STATUS EXIT_SUCCESS
    25	#endif
    26	
    27	#if EXIT_STATUS == EXIT_SUCCESS
    28	# define PROGRAM_NAME "true"
    29	#else
    30	# define PROGRAM_NAME "false"
    31	#endif

ということは、false.cのソースはどうなっているのでしょう。
先ほどtrue.cのソースファイルを指定したので、^置換前^置換後^で実行すれば良いです。

takk@deb83:~$ ^true^false^
cat -n /usr/src/coreutils/src/false.c
     1	#define EXIT_STATUS EXIT_FAILURE
     2	#include "true.c"
takk@deb83:~$ 

なんとfalse.cではtrue.cをインクルードしてました。
なるほど、trueとfalse表裏一体のようなプログラムなら、一つだけ作っておけば将来的に片側だけの修正で済むということですね。

コメント

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