77#define E_NOT_FOUND 0
88#define E_DIRECTORY 1
99#define E_PERMISSION 2
10+ #define E_INVALID_ARG 3
1011
11- void print (int file );
12+ typedef struct options {
13+ int number ;
14+ } Options ;
15+
16+ void print (int file , Options options );
17+ void itoa (int n , char s []);
18+ void reverse (char s []);
1219void error (int e_type , char * name );
1320
1421int main (int argc , char * argv [])
1522{
16- int file ;
23+ int file , c ;
24+ int number = 0 ;
25+ Options options = { 0 };
1726 struct stat stduf ;
1827
19- if (-- argc > 0 ) {
20- while (* ++ argv ) {
21- stat (* argv , & stduf );
22- if ((stduf .st_mode & S_IFMT ) == S_IFDIR ) {
23- error (E_DIRECTORY , * argv );
24- break ;
28+ // 引数がない場合は標準入力から読み込んで出力
29+ if (argc > 1 ) {
30+ while (-- argc > 0 && (* ++ argv )[0 ] == '-' ) {
31+ //引数がハイフンだけだった場合は標準入力から読み込んで出力
32+ if (* ++ argv [0 ] == NULL ) {
33+ print (0 , options );
34+ return 0 ;
2535 }
26- if (access (* argv , F_OK ) != 0 ) {
27- error (E_NOT_FOUND , * argv );
28- break ;
29- } else {
30- if (access (* argv , R_OK ) != 0 ) {
31- error (E_PERMISSION , * argv );
32- break ;
36+ while ((c = * argv [0 ]++ )) {
37+ switch (c ) {
38+ case 'n' :
39+ options .number = 1 ;
40+ break ;
41+ default :
42+ // cat -[invalid arguments]とした場合、エラーメッセージには一番最初の不正なオプションのみを表示する
43+ // (例) cat -aho の場合、cat: illegal option -- a
44+ argv [0 ]-- ;
45+ (* argv )[1 ] = '\0' ;
46+ error (E_INVALID_ARG , * argv );
47+ return 1 ;
3348 }
3449 }
35-
36- file = open (* argv , O_RDONLY , 0 );
37- print (file );
38- close (file );
3950 }
51+
52+ // オプションだけ指定した場合は標準入力から読み込んで出力
53+ if (argc > 0 ) {
54+ while (* argv ) {
55+ stat (* argv , & stduf );
56+ if ((stduf .st_mode & S_IFMT ) == S_IFDIR ) {
57+ error (E_DIRECTORY , * argv );
58+ break ;
59+ }
60+ if (access (* argv , F_OK ) != 0 ) {
61+ error (E_NOT_FOUND , * argv );
62+ break ;
63+ } else {
64+ if (access (* argv , R_OK ) != 0 ) {
65+ error (E_PERMISSION , * argv );
66+ break ;
67+ }
68+ }
69+
70+ file = open (* argv , O_RDONLY , 0 );
71+ print (file , options );
72+ close (file );
73+ argv ++ ;
74+ }
75+ } else
76+ print (0 , options );
4077 } else
41- print (0 );
78+ print (0 , options );
4279 return 0 ;
4380}
4481
4582#define BUFSIZE 1000
83+ #define MAXSIZE 1000
84+
85+ void print (int file , Options options )
86+ {
87+ // -nオプション
88+ if (options .number ) {
89+ char c ;
90+ int n , i = 0 , lc = 1 ;
91+ char line [MAXSIZE ], lc_char [10 ];
92+
93+ while ((n = read (file , & c , 1 )) == 1 ) {
94+ line [i ] = c ;
95+ i ++ ;
96+ if (c == '\n' ) {
97+ itoa (lc ++ , lc_char );
98+ line [i ] = '\0' ;
99+
100+ write (1 , " " , strlen (" " ));
101+ write (1 , lc_char , strlen (lc_char ));
102+ write (1 , " " , strlen (" " ));
103+ write (1 , line , strlen (line ));
104+
105+ i = 0 ;
106+ }
107+ }
108+ } else {
109+ char buf [BUFSIZE ];
110+ int n ;
111+
112+ while ((n = read (file , buf , BUFSIZE )) > 0 )
113+ write (1 , buf , n );
114+ }
46115
47- void print (int file )
116+
117+ }
118+
119+ void itoa (int n , char s [])
48120{
49- char buf [BUFSIZE ];
50- int n ;
121+ int i , sign ;
122+
123+ if ((sign = n ) < 0 )
124+ n = - n ;
125+ i = 0 ;
126+ do {
127+ s [i ++ ] = n % 10 + '0' ;
128+ } while ((n /= 10 ) > 0 );
51129
52- while ((n = read (file , buf , BUFSIZE )) > 0 )
53- write (1 , buf , n );
130+ if (sign < 0 )
131+ s [i ++ ] = '-' ;
132+ s [i ] = '\0' ;
133+ reverse (s );
134+ }
135+
136+ void reverse (char s [])
137+ {
138+ int c , i , j ;
139+
140+ for (i = 0 , j = strlen (s )- 1 ; i < j ; i ++ , j -- ) {
141+ c = s [i ];
142+ s [i ] = s [j ];
143+ s [j ] = c ;
144+ }
54145}
55146
56147#define ERROR_MSG_SIZE 256
@@ -73,6 +164,11 @@ void error(int e_type, char *name)
73164 strcat (error_msg , name );
74165 strcat (error_msg , ": Permission denied" );
75166 break ;
167+ case E_INVALID_ARG :
168+ strcat (error_msg , "illegal option -- " );
169+ strcat (error_msg , name );
170+ strcat (error_msg , "\nusage: cat [-n] [file ...]" );
171+ break ;
76172 default :
77173 break ;
78174 }
0 commit comments