1 /*****************************************
2 xjump version 2
3
4 record.c ������Ͽ
5
6 (C) July 16, 1997 ROYALPANDA
7 *****************************************/
8
9 #include<stdio.h>
10 #include<unistd.h>
11 #include<sys/types.h>
12 #include<fcntl.h>
13 #include<sys/file.h>
14 #include<errno.h>
15 #include<ctype.h>
16 #include<pwd.h>
17
18 #include"record.h"
19
20
21 /* ���ڡ����ɤ����Ф� */
22
skipspace(FILE * fp)23 static int skipspace( FILE *fp )
24 {
25 int c;
26
27 for(;;){
28 c = fgetc(fp);
29 if( c == EOF )
30 return -1;
31 if( c == '\n' )
32 return -1;
33 if( !isspace(c) ){
34 ungetc(c,fp);
35 return 0;
36 }
37 }
38 }
39
40
41 /* �����ɤ߹��� */
42
read_num(FILE * fp)43 static int read_num( FILE *fp )
44 {
45 int c,i;
46 int err;
47
48 if( skipspace( fp ) )
49 return -1;
50
51 i = 0;
52 err = 1;
53
54 for(;;){
55 c = fgetc( fp );
56 if( isdigit( c ) ){
57 i = i * 10 + c - '0';
58 err = 0;
59 }else
60 break;
61 }
62 ungetc( c,fp );
63
64 if( err )
65 return -1;
66 else
67 return i;
68 }
69
70 /* ̾�����ɤ߹��� */
71
read_name(char * buf,FILE * fp)72 static void read_name( char *buf, FILE *fp )
73 {
74 int l,c;
75
76 if( skipspace( fp ) ){
77 *buf = '\0';
78 return;
79 }
80
81 for( l = 0 ; l < 31 ; l++ ){
82 c = fgetc( fp );
83 if( c < 0 || iscntrl( c ) ){
84 ungetc( c,fp );
85 break;
86 }
87 *buf++ = c;
88 }
89 *buf = '\0';
90 }
91
92
93 /* �����ޤ��ɤ����Ф� */
94
void_line(FILE * fp)95 static void void_line( FILE *fp )
96 {
97 int c;
98
99 while( ( c = fgetc(fp) ) != '\n' && c != EOF )
100 ;
101 }
102
103
104 /* UID����ꥢ��͡������Ф� */
105
get_name(int uid,char * name)106 static char *get_name( int uid, char *name )
107 {
108 struct passwd *pw;
109 int i;
110
111 if( ( pw = getpwuid( uid ) ) == NULL )
112 name[0] = '\0';
113
114 else{
115
116 i = 0;
117 while( i < 31 && pw->pw_gecos[i] != '\0' && pw->pw_gecos[i] != ',' ){
118 name[i] = pw->pw_gecos[i];
119 i++;
120 }
121
122 if( i > 0 )
123 name[i] = '\0';
124 else
125 strcpy( name,pw->pw_name );
126
127 }
128
129 return name;
130 }
131
132
133 /*���쥳���ɤΣ�����ȥ�ɤ߹��ߡ�*/
134
read_entry(FILE * fp,record_t * rec)135 static int read_entry( FILE *fp, record_t *rec )
136 {
137 if( ( rec->score = read_num( fp ) ) < 0 )
138 return -1;
139
140 if( ( rec->uid = read_num( fp ) ) < 0 )
141 return -1;
142
143 read_name( rec->name,fp );
144 if( rec->name[0] == '\0' )
145 get_name( rec->uid,rec->name );
146
147 return 0;
148 }
149
150
151 /* �쥳�����ɤߤ��� */
152
read_record(FILE * fp)153 static void read_record( FILE *fp )
154 {
155 int i;
156
157 i = 0;
158
159 while( !feof( fp ) && i < RECORD_ENTRY ){
160 if( read_entry( fp,&Record[i] ) == 0 )
161 i++;
162 void_line( fp );
163 }
164 Record_entry = i;
165 }
166
167
168
169 /* ���顼 */
170
error(void)171 static void error( void )
172 {
173 perror( Myname );
174 fprintf( stderr,"%s: do not record high-score.\n",Myname);
175
176 Record_entry = -1;
177 }
178
179
180 /* �쥳���ɴط��ν���� */
181
init_record(void)182 void init_record( void )
183 {
184 FILE *fp;
185
186 Record_entry = -1;
187
188 if( ( fp = fopen( RECORD_FILE,"r+" ) ) == NULL ){
189 error();
190 return;
191 }
192 flock( fileno(fp),LOCK_EX );
193 read_record( fp );
194 fclose( fp );
195 }
196
197
198 /* ��������Ӵؿ� */
199
sort_cmp(record_t * r1,record_t * r2)200 static int sort_cmp( record_t *r1, record_t *r2 )
201 {
202 if( r1->score > r2->score )
203 return -1;
204 else if( r1->score < r2->score )
205 return 1;
206
207 else if( r1->rank > r2->rank )
208 return 1;
209 else
210 return -1;
211 }
212
213
214
215 /* ������ */
216
sort_record(void)217 static void sort_record( void )
218 {
219 int i;
220
221 for( i = 0 ; i < Record_entry ; i++ )
222 Record[i].rank = i;
223
224 qsort( Record,Record_entry,sizeof(record_t),sort_cmp );
225 }
226
227
228
229 /* �쥳���ɵ�Ͽ */
230
save_record(int sc)231 void save_record( int sc )
232 {
233 FILE *fp;
234 int i,r;
235 int uid;
236
237 if( Record_entry == -1 )
238 return ;
239
240 if( (fp = fopen(RECORD_FILE,"r+")) == NULL ){
241 error();
242 return;
243 }
244
245 flock( fileno(fp),LOCK_EX );
246 read_record( fp );
247
248 r = -1;
249 uid = (int)getuid();
250
251 for( i = 0 ; i < Record_entry ; i++ )
252 if( Record[i].uid == uid ){
253 r = i;
254 break;
255 }
256
257 if( r == -1 ){
258 if( Record_entry < RECORD_ENTRY ){
259 r = Record_entry++;
260 Record[r].score = 0;
261 }else
262 r = RECORD_ENTRY - 1;
263 }
264
265 if( sc > Record[r].score ){
266 Record[r].score = sc;
267 Record[r].uid = uid;
268 get_name( uid,Record[r].name );
269
270 sort_record();
271
272 rewind( fp );
273 ftruncate( fileno(fp) ,0 );
274 for( i = 0 ; i < Record_entry ; i++ )
275 fprintf( fp,"%d %d %s\n",
276 Record[i].score,Record[i].uid,Record[i].name );
277
278 fclose( fp );
279 return;
280 }
281 fclose( fp );
282 }
283