自作のtail(その5)

前回の続きです。自作のtailの末尾Byte抽出を複数のファイルに対応します。

今回の自作tailで読み込ませるバイナリ作成。

takk@deb9:~/tmp$ echo 0 010203 | xxd -rp > a.bin
takk@deb9:~/tmp$ echo 0 040506 | xxd -rp > b.bin
takk@deb9:~/tmp$ od -tx1 a.bin
0000000 01 02 03
0000003
takk@deb9:~/tmp$ od -tx1 b.bin
0000000 04 05 06
0000003
takk@deb9:~/tmp$ 

本物tailの動きを確認します。

takk@deb9:~/tmp$ tail -c2 a.bin b.bin | od -tx1c
0000000  3d  3d  3e  20  61  2e  62  69  6e  20  3c  3d  3d  0a  02  03
          =   =   >       a   .   b   i   n       < = = \n 002 003 0000020 0a 3d 3d 3e 20 62 2e 62 69 6e 20 3c 3d 3d 0a 05 \n = = >       b   .   b   i   n       <   =   =  \n 005
0000040  06
        006
0000041
takk@deb9:~/tmp$ 

行抽出と同じく、-cオプション指定時のByte抽出でも、
==> a.bin <==や==> b.bin <==といった見出しが表示されています。

この見出しを表示する処理と、ファイル数分ループする処理を、前回のプログラムに加えたのがこれです。

takk@deb9:~/tmp$ cat -n t.c
     1	#include <stdio.h>
     2	#include <sys/types.h>	//stat
     3	#include <sys/stat.h>	//stat
     4	#include <unistd.h>	//stat
     5	#include <getopt.h>	//getopt
     6	#include <stdlib.h>	//atoi
     7	
     8	int main(int argc, char* argv[])
     9	{
    10		int c;
    11		FILE *fp;
    12		char *fname;
    13		struct stat fs;
    14		int len = 10;
    15		int optch;
    16	
    17		while ((optch = getopt(argc, argv, "c:")) != -1){
    18			switch (optch) {
    19			case 'c':   
    20				len = atoi(optarg);
    21				break;
    22			default:
    23				printf("parameter error\n");
    24				return 1;
    25			}
    26		}
    27	
    28		argv += optind;
    29		argc -= optind;
    30	
    31		while(argc--){
    32			fname = *argv++;
    33			printf("<== %s ==>\n",fname);
    34	
    35			stat(fname, &fs);
    36	
    37			len = fs.st_size < len ? fs.st_size : len;
    38	
    39			fp=fopen(fname,"r");
    40			if(fseek(fp,-len,SEEK_END) != 0){
    41				perror("ERROR");
    42			}
    43			while((c=fgetc(fp)) != -1){
    44				putchar(c);
    45			}
    46			fclose(fp);
    47		}
    48	
    49		return 0;
    50	}
takk@deb9:~/tmp$ 

31と33、47行目が、複数ファイル処理のために追加した箇所です。

ビルド後、実行します。

takk@deb9:~/tmp$ ./a.out -c2 a.bin b.bin | od -tx1c
0000000  3c  3d  3d  20  61  2e  62  69  6e  20  3d  3d  3e  0a  02  03
          < = = a . b i n = = >  \n 002 003
0000020  3c  3d  3d  20  62  2e  62  69  6e  20  3d  3d  3e  0a  05  06
          < = = b . b i n = = >  \n 005 006
0000040
takk@deb9:~/tmp$ 

なんとなく、たぶん合ってるのだろうけど、情報が多くて比較しにくいので、見出しを非表示にしてみましょう。
本物のtailコマンドでは、-qオプションで、見出しを非表示にできます。同じように、自作tailにも-qオプションを追加してみます。

takk@deb9:~/tmp$ cat -n t.c

~省略~

    16		int qflag=0;
    17	
    18		while ((optch = getopt(argc, argv, "c:q")) != -1){
    19			switch (optch) {
    20			case 'c':   
    21				len = atoi(optarg);
    22				break;
    23			case 'q':   
    24				qflag = 1;
    25				break;
    26			default:

~省略~

    35		while(argc--){
    36			fname = *argv++;
    37			if(!qflag)
    38				printf("<== %s ==>\n",fname);

~省略~

takk@deb9:~/tmp$ 

-qオプションの対応は、数行付け足すだけです。
-qオプションが指定されたら、qflagを1にして、qflagが1の場合は、見出しを表示しないようにします。

さて、-qオプションを使って結果をシンプルにできるようになったので、比較してみましょう。

自作tail。

takk@deb9:~/tmp$ ./a.out -qc2 a.bin b.bin | od -tx1
0000000 02 03 05 06
0000004
takk@deb9:~/tmp$ 

本物tail。

takk@deb9:~/tmp$ tail -qc2 a.bin b.bin | od -tx1
0000000 02 03 05 06
0000004
takk@deb9:~/tmp$ 

一致しました。

つづく

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA