Cat(Concatenate)
2013/03/01(Fri) 更新.
catコマンドに似せたものを作りました.
今回はロングオプションを対応させてみました.
行数を表示させる為に悠長な書き方をしてしまいましたが...
/* Pseudeo cat command
* Author: Jin
* Version: 2.0.0
* Date: 2013/03/01(Fri)
* *********************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<getopt.h>
#include<sys/stat.h>
#include<sys/types.h>
#define BUFFSIZE 65536 /* Limit */
#ifdef EOF
#define EOF (-1)
#else
#define EOF (-1)
#endif
#define ON_MODE 1
#define OFF_MODE 0
static struct option longopt[] = {
{"number", optional_argument, 0, 'n'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
{0, 0, 0, 0},
};
static char buff[BUFFSIZE] = {"\0"};
void no_arg_cat(void); /* No Argument Mode */
void print_cat(const char *name); /* No Option Mode */
void print_number(const char *name); /* Number Option Mode */
void print_help(void);
void print_version(void);
void error_message(const char *path);
int main(int argc, char **argv)
{
int opt, optindex, i;
int f_help, f_ver, f_number;
f_help = f_ver = f_number = OFF_MODE;
if(argc < 2)
no_arg_cat();
while((opt = getopt_long(argc, argv, "hvna:",
longopt, &optindex)) != EOF) {
switch(opt) {
case 'h':
f_help = ON_MODE;
break;
case 'v':
f_ver = ON_MODE;
break;
case 'n':
f_number = ON_MODE;
break;
case '?':
f_help = ON_MODE;
break;
default:
f_help = ON_MODE;
break;
}
}
if(f_help || f_ver) {
if(f_help) print_help();
if(f_ver) print_version();
exit(EXIT_SUCCESS);
}
else if(f_number) {
/* Option `n` Mode */
if(argc == optind)
no_arg_cat();
for(i = optind; i < argc; i++)
print_number(argv[i]);
}
else {
for(i = 1; i < argc; i++)
print_cat(argv[i]);
}
return 0;
}
void no_arg_cat(void) { /* No Argument Mode */
/* Use System Call */
int nbyte;
while(1) {
if((nbyte = read(0, buff, BUFFSIZE)) == EOF)
error_message("read");
if(nbyte == 0) break; /* Normality End */
if(write(1, buff, nbyte) == EOF)
error_message("write");
}
}
void print_cat(const char *name) { /* No Option Mode */
/* Use System Call */
int fd, nbyte;
if((fd = open(name, O_RDONLY)) == EOF)
error_message("open");
while(1) {
if((nbyte = read(fd, buff, BUFFSIZE)) == EOF)
error_message("read");
if(nbyte == 0) break; /* Normality End */
if(write(1, buff, nbyte) == EOF)
error_message("write");
}
close(fd);
}
void print_number(const char *name) { /* Number Option Mode */
/* Library Calls */
FILE *fp;
int i = 1;
if((fp = fopen(name, "r")) == NULL)
error_message("fopen");
while(fgets(buff, sizeof(buff), fp))
printf("%6d %s", i++, buff);
fclose(fp);
}
void print_help(void) {
printf("Usage: cat [Option]... [File]...\n \
\n \
-n, --number : Print Number.\n \
-h, --help : Print Help.\n \
-v, --version : Print Version.\n\n");
}
void print_version(void) {
printf("Version: 2.0.0\n");
}
void error_message(const char *path) {
perror(path);
exit(EXIT_FAILURE);
}
実行例:
$ ./cat --help
Usage: cat [Option] [Filename]...
-n, --number : 全ての行に番号を付けて出力します.
-v, --version : バージョンを表示します.
-h, --help : catコマンドのヘルプを表示します.(このページ)