■C: Linuxでの基本的なプログラム
■コマンドライン引数の表示
$ vi args.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
printf("argc=%d\n", argc);
for (i = 0; i < argc; i++) {
printf("argc[%d]=%s\n", i, argv[i]);
}
exit(0);
}
$ gcc -o args args.c
$ ./args
argc=1
argc[0]=./args
$ ./args x y z
argc=4
argc[0]=./args
argc[1]=x
argc[2]=y
argc[3]=z
■標準Cライブラリの場所
$ ls /lib64/libc.so.6
/lib64/libc.so.6
$ ls -l /lib64/libc.so.6
lrwxrwxrwx. 1 root root 12 12月 27 02:19 /lib64/libc.so.6 -> libc-2.17.so
■catコマンドを作る
$ vi cat.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++) {
FILE *f;
int c;
f = fopen(argv[i], "r");
if (!f) {
perror(argv[i]);
exit(1);
}
while ((c = fgetc(f)) != EOF) {
if (putchar(c) < 0) exit(1);
//if (fputc(c, stdout) < 0) exit(1);
}
fclose(f);
}
exit(0);
}
$ gcc -o cat cat.c
$ ./cat
$ ./cat cat.c
■headコマンドを作る(処理対象は標準出力のみ)
$ vi head.c
#include <stdio.h>
#include <stdlib.h>
static void do_head(FILE *f, long nlines);
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage: %s n\n", argv[0]);
exit(1);
}
do_head(stdin, atol(argv[1]));
exit(0);
}
static void do_head(FILE *f, long nlines) {
int c;
if (nlines <= 0) return;
while ((c = getc(f)) != EOF) {
if (putchar(c) < 0) exit(1);
if (c == '\n') {
nlines--;
if (nlines == 0) return;
}
}
}
$ gcc -o head head.c
$ ./head
$ cat head.c | ./head 5
■headコマンドを作る(引数でファイルを指定)
$ vi head.c
#include <stdio.h>
#include <stdlib.h>
static void do_head(FILE *f, long nlines);
int main(int argc, char *argv[])
{
long nlines;
if (argc < 2) {
fprintf(stderr, "Usage: %s n [file file...]\n", argv[0]);
exit(1);
}
nlines = atol(argv[1]);
if (argc == 2) {
do_head(stdin, atol(argv[1]));
} else {
int i;
for (i = 2; i < argc; i++) {
FILE *f;
f = fopen(argv[i], "r");
if (!f) {
perror(argv[i]);
exit(1);
}
do_head(f, nlines);
fclose(f);
}
}
exit(0);
}
static void do_head(FILE *f, long nlines) {
int c;
if (nlines <= 0) return;
while ((c = getc(f)) != EOF) {
if (putchar(c) < 0) exit(1);
if (c == '\n') {
nlines--;
if (nlines == 0) return;
}
}
}
$ gcc -o head head.c
$ ./head
$ cat head.c | ./head 5
$ ./head 5 head.c
■headコマンドを作る(オプションを扱う)
$ vi head.c
#include <stdio.h>
#include <stdlib.h>
/* getopt_long() のプロトタイプ宣言を取り込む */
#define _GNU_SOURCE
#include <getopt.h>
static void do_head(FILE *f, long nlines);
#define DEFAULT_N_LINES 10
/* ロングオプションの仕様を定義する */
static struct option longopts[] = {
{"lines", required_argument, NULL, 'n'},
{"help", no_argument, NULL, 'h'},
{0, 0, 0, 0 }
};
int main(int argc, char *argv[])
{
int opt;
long nlines;
/* オプションを解析するループ */
while ((opt = getopt_long(argc, argv, "n:", longopts, NULL)) != -1) {
switch (opt) {
case 'n':
nlines = atol(optarg);
break;
case 'h':
fprintf(stdout, "Usage: %s [-n LINES] [FILE ...]\n", argv[0]);
exit(0);
case '?':
fprintf(stderr, "Usage: %s [-n LINES] [FILE ...]\n", argv[0]);
exit(1);
}
}
/*
* optind は現在処理中のオプションのargvでのインデックスが入るグローバル変数
* この場合、オプションではない最初の引数のインデックスを指している
*/
if (optind == argc) {
do_head(stdin, nlines);
} else {
int i;
for (i = optind; i < argc; i++) {
FILE *f;
f = fopen(argv[i], "r");
if (!f) {
perror(argv[i]);
exit(1);
}
do_head(f, nlines);
fclose(f);
}
}
exit(0);
}
static void do_head(FILE *f, long nlines) {
int c;
if (nlines <= 0) return;
while ((c = getc(f)) != EOF) {
if (putchar(c) < 0) exit(1);
if (c == '\n') {
nlines--;
if (nlines == 0) return;
}
}
}
$ gcc -o head head.c
$ ./head -n 5 head.c
$ cat head.c | ./head -n 5
■grepコマンドを作る
$ vi grep.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <regex.h>
static void do_grep(FILE *f, regex_t *pat);
int main(int argc, char *argv[])
{
regex_t pat;
int err;
if (argc < 2) {
fputs("no pattern\n", stderr);
exit(1);
}
/* 文字列で表現されている正規表現パターンを、専用のデータ型(regex_t)に変換する */
err = regcomp(&pat, argv[1], REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
if (err != 0) {
char buf[1024];
/* regcomp() のエラーコードをエラーメッセージに変換する */
regerror(err, &pat, buf, sizeof buf);
puts(buf);
exit(1);
}
if (argc == 2) {
do_grep(stdin, &pat);
} else {
int i;
for (i = 2; i < argc; i++) {
FILE *f;
f = fopen(argv[i], "r");
if (!f) {
perror(argv[i]);
exit(1);
}
do_grep(f, &pat);
fclose(f);
}
}
/* regcomp() で確保したメモリを開放する */
regfree(&pat);
exit(0);
}
static void do_grep(FILE *f, regex_t *pat) {
char buf[4096];
/* 正規表現に適合するか調べるために、バイト単位ではなく行単位で読み込む */
while (fgets(buf, sizeof buf, f)) {
/* 正規表現に適合する行のみを出力する */
if (regexec(pat, buf, 0, NULL, 0) == 0) {
fputs(buf, stdout);
}
}
}
$ gcc -o grep grep.c
$ ./grep pat grep.c
■lsコマンドを作る
$ vi ls.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
static void do_ls(char *path);
int main(int argc, char *argv[])
{
int i;
if (argc < 2) {
fprintf(stderr, "%s: no arguments\n", argv[0]);
exit(1);
}
for (i = 1; i < argc; i++) {
do_ls(argv[1]);
}
exit(0);
}
static void do_ls(char *path) {
DIR *d;
struct dirent *ent;
d = opendir(path);
if (!d) {
perror(path);
exit(1);
}
while (ent =readdir(d)) {
printf("%s\n", ent->d_name);
}
closedir(d);
}
$ gcc -o ls ls.c
$ ./ls .
■mkdirコマンドを作る
$ vi mkdir.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc, char *argv[])
{
int i;
if (argc < 2) {
fprintf(stderr, "%s: no arguments\n", argv[0]);
exit(1);
}
for (i = 1; i < argc; i++) {
if (mkdir(argv[i], 0777) < 0) {
perror(argv[i]);
exit(1);
}
}
exit(0);
}
$ gcc -o mkdir mkdir.c
$ ./mkdir test
■rmdirコマンドを作る
$ vi mkdir.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int i;
if (argc < 2) {
fprintf(stderr, "%s: no arguments\n", argv[0]);
exit(1);
}
for (i = 1; i < argc; i++) {
if (rmdir(argv[i]) < 0) {
perror(argv[i]);
exit(1);
}
}
exit(0);
}
$ gcc -o rmdir rmdir.c
$ ./rmdir test
■unlinkコマンドを作る
$ vi mkdir.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int i;
if (argc < 2) {
fprintf(stderr, "%s: no arguments\n", argv[0]);
exit(1);
}
for (i = 1; i < argc; i++) {
if (unlink(argv[i]) < 0) {
perror(argv[i]);
exit(1);
}
}
exit(0);
}
$ gcc -o unlink unlink.c
$ ./unlink test.txt
■mvコマンドを作る
$ vi mv.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int i;
if (argc != 3) {
fprintf(stderr, "%s: wrong arguments\n", argv[0]);
exit(1);
}
if (rename(argv[1], argv[2]) < 0) {
perror(argv[1]);
exit(1);
}
exit(0);
}
$ gcc -o mv mv.c
$ ./mv test1.txt test2.txt