🦔

[C言語]簡単なLinuxコマンドを作成してみる

2022/09/04に公開

はじめに

C言語を暫く使っていないため、久しぶりに使いたくなった。
そこで、Linuxの復習も兼ねて、Linuxコマンドを作成してみる。
尚、単純に引数として渡された数値の合計を足し算するだけのコマンドなため、実用性は皆無。

目的

  • 自分でコマンドを作成することで、Linuxコマンドをイメージできるようにする
  • Linuxがコマンドを実行する際に参照するPATHの概念を理解する
    上記のため、実装についての詳細な説明は割愛する。

もちろん、質問はご自由にどうぞ!
答えられる範囲で回答します。

環境

  • Amazon Linux AMI release 2018.03 ※Cloud9

仕様

  • コマンドライン引数に渡した数値の合計を標準出力に出力
  • 引数として渡す数値の数は2つ以上とする
  • 細かいエラー処理は割愛
     渡される数値の個数の上限だとか数値自体の下限上限等は気にしない。

手順

1. テスト用のディレクトリを作成

ソースコードを置くためのディレクトリを作成。
今回は適当に「test」としているが、名前は任意で良い。

テスト用のディレクトリを作成
# ディレクトリを作成、移動
$ mkdir test; cd test

2. ソースコードファイルを作成

ここではviで記載しているが、テキストエディタはなんでも良い。

ソースコードファイル作成
$ vi test_sum.c

3. 実装

以下のソースコードをコピペ。

test_sum.c
#include <stdio.h>

int main(int argc, char *argv[])
{
  int sum = 0;
  int count = 0;

  if (argc < 3) {
    printf("ERROR: invalid of arguments number\n");
    return 1;
  }

  /* argv[0]はコマンド自身のため、計算対象から除外するため、count=1から開始 */
  for (count=1; count<argc; count++) {
    sum += atoi(argv[count]);
  }
  printf("%d\n", sum);

  return 0;
}

尚、atoiは最上位の桁から変換していき、数字以外の文字を検出した時点で変換を停止させる。
例)"a":変換できるものがないため、0を返す。
 "1a3":最上位の1は変換するが、aを検出したため変換を停止、1を返す。

4. コンパイル

gccを使い、ソースコードをコンパイル

コンパイル
# -oで成果物の名前を指定(指定がないとa.outになってしまう)
$ gcc -o test_sum test_sum.c

動作は単純なものの、これでtest_sumというコマンドが完成!

5. 簡単な動作確認

自作したtest_sumを使用してみる。
以下、いくつかのパターンでお試し。

test_sumを使った計算
$ ./test_sum 123
ERROR: invalid of arguments number
$ ./test_sum 123 23456
23579
$ ./test_sum 123 23456 812
24391

大成功!!
※最初のエラーは引数が少ない(3つ未満)の場合に出力しているエラー。

6. PATH設定

このままだと、毎回パス指定("./"のこと)が必要になってしまうため、他のコマンドのようにパス指定なしで動作するように設定していく。
※カレントディレクトリがコマンドと同じでも指定が必要になる。

6.1. PATHとは

Linuxが実行ファイル(ELF)を実行するときにファイルを探しに行くパスをまとめている環境変数のこと。
LinuxはPATHに設定されているパスを順番に探していき、最初に見つかった実行ファイルを実行する。
※lsとかfindとかが指定なしで使えるのはPATHに置き場所を保存してあるため。

6.2. PATHの設定

PATHなどの環境変数を設定するにはexportを使用する。
以下のコマンドで今いるディレクトリ(カレントディレクトリ)のパスをPATHに登録。

カレントディレクトリのパスをPATHに設定
$ export PATH=$PATH:$(pwd)

これで、どのディレクトリにいてもパス指定不要!
シェルを落としたときにこの設定は消えてしまうことに注意!!

6.3. 動作確認

適当にディレクトリ移動して動作確認をしてみる。

動作確認
$ test_sum 1 2 3
6
$ cd ~
$ test_sum 1 2 3
6
$ cd /tmp
$ test_sum 1 2 3
6

おまけ

lsやfindなどの既存のコマンドがどこにあるかを確認する場合、whichというコマンドを使用する。なお、作成したtest_sumもwhichコマンドで場所を確認できる。

コマンドのパスを確認
# whichのパスを確認
$ which ls
alias ls='ls --color=auto'
        /bin/ls

# findのパスを確認
$ which find
/bin/find

# test_sum(自作のコマンド)のパスを確認
$ which test_sum
~/environment/test/test_sum

Discussion