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