/***************************************** xjump version 2 record.c 得点記録 (C) July 16, 1997 ROYALPANDA *****************************************/ #include #include #include #include #include #include #include #include #include"record.h" /* スペース読み飛ばし */ static int skipspace( FILE *fp ) { int c; for(;;){ c = fgetc(fp); if( c == EOF ) return -1; if( c == '\n' ) return -1; if( !isspace(c) ){ ungetc(c,fp); return 0; } } } /* 数値読み込み */ static int read_num( FILE *fp ) { int c,i; int err; if( skipspace( fp ) ) return -1; i = 0; err = 1; for(;;){ c = fgetc( fp ); if( isdigit( c ) ){ i = i * 10 + c - '0'; err = 0; }else break; } ungetc( c,fp ); if( err ) return -1; else return i; } /* 名前の読み込み */ static void read_name( char *buf, FILE *fp ) { int l,c; if( skipspace( fp ) ){ *buf = '\0'; return; } for( l = 0 ; l < 31 ; l++ ){ c = fgetc( fp ); if( c < 0 || iscntrl( c ) ){ ungetc( c,fp ); break; } *buf++ = c; } *buf = '\0'; } /* 行末まで読み飛ばす */ static void void_line( FILE *fp ) { int c; while( ( c = fgetc(fp) ) != '\n' && c != EOF ) ; } /* UIDからリアルネームを取り出す */ static char *get_name( int uid, char *name ) { struct passwd *pw; int i; if( ( pw = getpwuid( uid ) ) == NULL ) name[0] = '\0'; else{ i = 0; while( i < 31 && pw->pw_gecos[i] != '\0' && pw->pw_gecos[i] != ',' ){ name[i] = pw->pw_gecos[i]; i++; } if( i > 0 ) name[i] = '\0'; else strcpy( name,pw->pw_name ); } return name; } /* レコードの1エントリー読み込み */ static int read_entry( FILE *fp, record_t *rec ) { if( ( rec->score = read_num( fp ) ) < 0 ) return -1; if( ( rec->uid = read_num( fp ) ) < 0 ) return -1; read_name( rec->name,fp ); if( rec->name[0] == '\0' ) get_name( rec->uid,rec->name ); return 0; } /* レコード読みだし */ static void read_record( FILE *fp ) { int i; i = 0; while( !feof( fp ) && i < RECORD_ENTRY ){ if( read_entry( fp,&Record[i] ) == 0 ) i++; void_line( fp ); } Record_entry = i; } /* エラー */ static void error( void ) { perror( Myname ); fprintf( stderr,"%s: do not record high-score.\n",Myname); Record_entry = -1; } /* レコード関係の初期化 */ void init_record( void ) { FILE *fp; Record_entry = -1; if( ( fp = fopen( RECORD_FILE,"r+" ) ) == NULL ){ error(); return; } flock( fileno(fp),LOCK_EX ); read_record( fp ); fclose( fp ); } /* ソート比較関数 */ static int sort_cmp( record_t *r1, record_t *r2 ) { if( r1->score > r2->score ) return -1; else if( r1->score < r2->score ) return 1; else if( r1->rank > r2->rank ) return 1; else return -1; } /* ソート */ static void sort_record( void ) { int i; for( i = 0 ; i < Record_entry ; i++ ) Record[i].rank = i; qsort( Record,Record_entry,sizeof(record_t),sort_cmp ); } /* レコード記録 */ void save_record( int sc ) { FILE *fp; int i,r; int uid; if( Record_entry == -1 ) return ; if( (fp = fopen(RECORD_FILE,"r+")) == NULL ){ error(); return; } flock( fileno(fp),LOCK_EX ); read_record( fp ); r = -1; uid = (int)getuid(); for( i = 0 ; i < Record_entry ; i++ ) if( Record[i].uid == uid ){ r = i; break; } if( r == -1 ){ if( Record_entry < RECORD_ENTRY ){ r = Record_entry++; Record[r].score = 0; }else r = RECORD_ENTRY - 1; } if( sc > Record[r].score ){ Record[r].score = sc; Record[r].uid = uid; get_name( uid,Record[r].name ); sort_record(); rewind( fp ); ftruncate( fileno(fp) ,0 ); for( i = 0 ; i < Record_entry ; i++ ) fprintf( fp,"%d %d %s\n", Record[i].score,Record[i].uid,Record[i].name ); fclose( fp ); return; } fclose( fp ); }