システム・プログラムI 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro1-1997/1997-05-06
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html
---------------------------------------------------------------------- 1: /* 2: errno-perror.c -- errno, perror() のテスト 3: /usr/local/LECTURES/syspro-1997-shinjo/env/errno-perror.c 4: $Header: errno-perror.c,v 1.1 97/05/05 17:00:28 yas Exp $ 5: Start: 1997/05/05 16:42:22 6: */ 7: 8: #include <errno.h> 9: 10: main() 11: { 12: errno = 0 ; 13: perror("0"); 14: errno = EACCES ; 15: perror("EACCES"); 16: } ----------------------------------------------------------------------実行例。
---------------------------------------------------------------------- % cat MakefileCFLAGS=-g % rm errno-perror
% make errno-perror
cc -g errno-perror.c -o errno-perror % ./errno-perror
0: エラー 0 EACCES: パーミッションがありません。 %
----------------------------------------------------------------------
---------------------------------------------------------------------- 1: /* 2: filter-char.c -- 文字単位の簡単なフィルタ 3: /usr/local/LECTURES/syspro-1997-shinjo/file/filter-char.c 4: $Header: filter-char.c,v 1.3 97/05/05 18:19:54 yas Exp $ 5: Start: 1997/04/21 18:23:13 6: */ 7: 8: #include <stdio.h> /* stdin, stdout, fopen(), fclose(), getc(), */ 9: #include <ctype.h> /* toupper() */ 10: 11: main( argc,argv ) 12: int argc ; 13: char *argv[] ; 14: { 15: int i ; 16: FILE *fp ; 17: if( argc == 1 ) 18: filter_char_upper( stdin, stdout ); 19: else 20: { 21: for( i=1 ; i< argc ; i++ ) 22: { 23: if( (fp = fopen( argv[i],"r" )) == NULL ) 24: { 25: perror( argv[i] ); 26: exit( -1 ); 27: } 28: filter_char_upper( fp, stdout ); 29: fclose( fp ); 30: } 31: } 32: } 33: 34: filter_char_upper( in, out ) 35: FILE *in, *out ; 36: { 37: int c ; /* int型。char は、不可 */ 38: while( (c=getc(in)) != EOF ) 39: { 40: putc( toupper(c),out ); 41: } 42: } ----------------------------------------------------------------------
fopen()は、ファイルを開くライブラリ関数である。"r" は、 読み込み専用で ファイルを開くことを意味している。fopen()は、結果として FILE 構造体へ のポインタを返す。これは、stdio.h で宣言されている配列 _iob[] の要素へ のポインタである。これは、次のようなライブラリ関数で使われる。
fgetc() fputs() getc() getw() fgets() fread() ungetc() fprintf() fscanf() fputc() fwrite() putc() putc() fflush() fseek() ftell() frewind() fclose() fdopen() freopen() ferrror() feof() clearerr() fileno()
このような、struct FILE を使うライブラリ関数群は、次のような名前で呼ば れる。
putc() は、第1引数で指定された文字を第2引数で与えられたストリームへ 出力する。
fclose() は、ファイルを閉じるライブラリ関数である。
実行例
---------------------------------------------------------------------- % ./filter-charabc
ABC asdfjkl;
ASDFJKL; ^D %
----------------------------------------------------------------------
---------------------------------------------------------------------- 1: /* 2: filestruct-print.c -- _filestruct[] の内容を表示する 3: /usr/local/LECTURES/syspro-1997-shinjo/file/filestruct-print.c 4: $Header: filestruct-print.c,v 1.2 97/05/05 18:58:37 yas Exp $ 5: Start: 1997/05/05 18:31:55 6: */ 7: 8: #include <stdio.h> 9: 10: main() 11: { 12: FILE *fp ; 13: 14: printf("stdin == 0x%x == &_iob[%d]\n",stdin, stdin-&_iob[0] ); 15: printf("stdout == 0x%x == &_iob[%d]\n",stdout, stdout-&_iob[0] ); 16: printf("stderr == 0x%x == &_iob[%d]\n",stderr, stderr-&_iob[0] ); 17: 18: fp = fopen("filestruct-print.c","r"); 19: printf("fp == 0x%x == &_iob[%d]\n",fp, fp-&_iob[0] ); 20: 21: printf("fopen()\n"); 22: filestruct_print( fp ); 23: getc( fp ); 24: printf("getc()\n"); 25: filestruct_print( fp ); 26: getc( fp ); 27: printf("getc()\n"); 28: filestruct_print( fp ); 29: fclose( fp ); 30: printf("fclose()\n"); 31: filestruct_print( fp ); 32: } 33: 34: #if 0 35: typedef struct { 36: int __cnt; 37: unsigned char *__ptr; 38: unsigned char *__base; 39: unsigned short __flag; 40: unsigned char __fileL; /* low byte of file desc */ 41: unsigned char __fileH; /* high byte of file desc */ 42: } FILE; 43: #endif 0 44: 45: filestruct_print( fp ) 46: FILE *fp ; 47: { 48: printf("cnt:%d, ptr:0x%x, base:0x%x, flag:0%x, fileL:%d, fileH:%d\n", 49: fp->__cnt, fp->__ptr, fp->__base, fp->__flag, 50: fp->__fileL,fp->__fileH); 51: } ---------------------------------------------------------------------- # define getc(__p) (--(__p)->__cnt >= 0 ? (int) *(__p)->__ptr++ : \ __filbuf(__p)) ----------------------------------------------------------------------
---------------------------------------------------------------------- % make filestruct-printcc -g filestruct-print.c -o filestruct-print % ./filestruct-print
stdin == 0x40001008 == &_iob[0] stdout == 0x40001018 == &_iob[1] stderr == 0x40001028 == &_iob[2] fp == 0x40001038 == &_iob[3] fopen() cnt:0, ptr:0x0, base:0x0, flag:01, fileL:3, fileH:0 getc() cnt:1253, ptr:0x400035e1, base:0x400035e0, flag:09, fileL:3, fileH:0 getc() cnt:1252, ptr:0x400035e2, base:0x400035e0, flag:09, fileL:3, fileH:0 fclose() cnt:0, ptr:0x0, base:0x0, flag:00, fileL:3, fileH:0 %
----------------------------------------------------------------------
UNIXでは、ファイルは、バイト列である。ファイルの内容として文字だけのも のを、テキスト・ファイルという。テキスト・ファイル以外のものは、バイナ リ・ファイルという。
UNIXのテキスト・ファイルでは、行末に \n が入っている。このようなテキス ト・ファイルは、テキスト・エディタ(emacs,mule,vi)で作られる。grep, sed, awk, sort などのフィルタで処理することができる。
テキスト・ファイルの入出力には、fgets(), fputs(), fprintf() などを使う とよい。(gets(), fscanf(), scanf() は、セキュリティ・ホールになりやす いので、なるべく使わない。)
fread(), fwrite() を使う。
ポータビリティ(別のOSやCPUのコンピュータでも使う)を考える時には、 文字コード、バイトオーダー、浮動小数点の形式、構造体の穴に注意する。 XDR ライブラリを使えば、ポータビリティが高くなる。(XDR については、3 学期の「分散システム」で。)
---------------------------------------------------------------------- 1: 2: /* 3: utmp/print.c -- /etc/utmp ファイルの内容を表示するプログラム 4: /usr/local/LECTURES/syspro-1997-shinjo/file/utmp-print.c 5: $Header: utmp-print.c,v 1.2 97/05/05 21:38:41 yas Exp $ 6: Start: 1995/03/06 09:01:09 7: */ 8: 9: #include <stdio.h> /* FILE, NULL, stderr */ 10: #include <sys/types.h> /* struct utmp */ 11: #include <utmp.h> /* struct utmp */ 12: 13: #if 0 14: struct utmp { 15: char ut_user[8]; /* User login name */ 16: char ut_id[4]; /* /etc/inittab id (usually line #) */ 17: char ut_line[12]; /* device name (console, lnxx) */ 18: pid_t ut_pid; /* process id */ 19: short ut_type; /* type of entry */ 20: struct exit_status { 21: short e_termination; /* Process termination status */ 22: short e_exit; /* Process exit status */ 23: } ut_exit; /* The exit status of a process */ 24: /* marked as DEAD_PROCESS. */ 25: unsigned short ut_reserved1; /* Reserved for future use */ 26: time_t ut_time; /* time entry was made */ 27: char ut_host[16]; /* host name, if remote */ 28: unsigned long ut_addr; /* Internet addr of host, if remote */ 29: }; 30: #endif 0 31: 32: main() 33: { 34: utmp_print_file(); 35: } 36: 37: utmp_print_file() 38: { 39: struct utmp entry; 40: FILE *fp ; 41: fp = fopen( UTMP_FILE, "r" ); 42: if( fp == NULL ) 43: { 44: perror( UTMP_FILE ); 45: exit( -1 ); 46: } 47: while( fread(&entry, sizeof(entry),1,fp ) == 1 ) 48: { 49: utmp_print( &entry ); 50: } 51: fclose( fp ); 52: } 53: 54: utmp_print( u ) 55: register struct utmp *u ; 56: { 57: print_char_array( u->ut_user, sizeof(u->ut_user) ); 58: print_char_array( u->ut_id, sizeof(u->ut_id) ); 59: print_char_array( u->ut_line, sizeof(u->ut_line) ); 60: printf("%d ", u->ut_type ); 61: printf("%6d ", u->ut_pid ); 62: print_char_array( u->ut_host, sizeof(u->ut_host) ); 63: printf("%s",ctime(&u->ut_time) ); 64: } 65: 66: print_char_array( a,len ) 67: char a[]; 68: int len ; 69: { 70: int i ; 71: for( i=0 ; i<len && a[i] ; i++ ) 72: putchar( a[i] ); 73: for( ; i<len ; i++ ) 74: putchar(' '); 75: putchar(' '); 76: } 77: 78: /* ------------------------ utmp-print.c ------------------------ */ 79: static char rcsid[] = 80: "$Header: utmp-print.c,v 1.2 97/05/05 21:38:41 yas Exp $" ; ----------------------------------------------------------------------実行結果
---------------------------------------------------------------------- % ./utmp-printsystem boot 2 0 Thu Apr 3 15:53:29 1997 run-level 3 1 0 Thu Apr 3 15:53:29 1997 bcheckrc brc1 8 12 Thu Apr 3 15:53:31 1997 recovers slib 8 22 Thu Apr 3 15:53:31 1997 brc brc2 8 23 Thu Apr 3 15:53:32 1997 sh link 8 31 Thu Apr 3 15:53:32 1997 rc rc 8 34 Thu Apr 3 15:54:44 1997 LOGIN vue console 6 9208 Sat May 3 00:03:53 1997 yas sb pty/ttysb 7 29433 top Mon May 5 16:20:57 1997 ... i?????? s0 pty/ttys0 8 910 Thu Apr 3 18:51:23 1997 i?????? s1 pty/ttys1 8 1134 Thu Apr 3 19:35:51 1997 i?????? sa pty/ttysa 8 6886 canna15 Sat May 3 00:03:43 1997 i?????? p2 pty/ttyp2 8 19806 Wed Apr 30 11:41:47 1997 yas s2 pty/ttys2 8 29156 Mon May 5 17:53:31 1997 ... e?????? s7 pty/ttys7 8 9379 canna15 Thu Apr 24 16:13:00 1997 % who
yas pty/ttysb May 5 16:20 %
----------------------------------------------------------------------
stdioライブラリ関数を持ちいて、次のようなフィルタを作りなさい。
入力: ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 出力: NOPQRSTUVWXYZABCDEFGHIJKLM nopqrstuvwxyzabcdefghijklmそれ以外のものは、そのまま出力する。この暗号法を rot13 (rotation)とい う。これは、まったく同じルーチンで暗号化と復号化ができる。 ネットワーク・ニュースなでど、ネタばらしの投稿に使われる。
UNIXの who コマンドと似た動きをするプログラムを作りなさい。