summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--UPDATING4
-rw-r--r--include/proto.h14
-rw-r--r--mbbsd/chicken.c291
-rw-r--r--mbbsd/talk.c20
-rw-r--r--upgrade/r3968_chicken.c110
5 files changed, 303 insertions, 136 deletions
diff --git a/UPDATING b/UPDATING
index 5af922f2..20180d44 100644
--- a/UPDATING
+++ b/UPDATING
@@ -15,6 +15,10 @@ https://opensvn.csie.org/traccgi/pttbbs/changeset/2273
-----------------------------------------------------------------------------
+r3968: [CHICKEN]
+把 Chicken 搬出 PASSWD, 並且改用 mmap 同步。
+請記得關站後執行 upgrade/r3968_chicken 轉移資料後再重開 BBS。
+
r3153: [CHESS]
chess framework update
!!!NOTE!!! Chess protocals are NOT backward compatible
diff --git a/include/proto.h b/include/proto.h
index 57388817..ebab4084 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -208,13 +208,12 @@ int chc_watch(void);
ChessInfo* chc_replay(FILE* fp);
/* chicken */
-void ch_buyitem(int money, const char *picture, int *item, int haveticket);
int chicken_main(void);
int chickenpk(int fd);
-void time_diff(chicken_t *thechicken);
-int isdeadth(const chicken_t *thechicken);
-void show_chicken_data(chicken_t *thechicken, chicken_t *pkchicken);
int reload_chicken(void);
+void chicken_query(const char *userid);
+void ch_buyitem(int money, const char *picture, int *item, int haveticket);
+void show_chicken_data(chicken_t *thechicken, chicken_t *pkchicken);
/* dark */
int main_dark(int fd,userinfo_t *uin);
@@ -557,13 +556,15 @@ inline
int getindex(const char *fpath, fileheader_t *fh, int start);
/* register */
+int u_register(void);
int getnewuserid(void);
int bad_user_id(const char *userid);
-void new_register(void);
int checkpasswd(const char *passwd, char *test);
+int setupnewuser(const userec_t *user);
+void new_register(void);
void check_register(void);
+void delregcodefile(void);
char *genpasswd(char *pw);
-int setupnewuser(const userec_t *user);
/* reversi */
void reversi(int s, ChessGameMode mode);
@@ -757,7 +758,6 @@ int u_ansi(void);
int u_editplan(void);
int u_editsig(void);
int u_cloak(void);
-int u_register(void);
int u_list(void);
#ifdef DBCSAWARE
int u_detectDBCSAwareEvilClient();
diff --git a/mbbsd/chicken.c b/mbbsd/chicken.c
index 8279d4f6..2e4354bb 100644
--- a/mbbsd/chicken.c
+++ b/mbbsd/chicken.c
@@ -5,6 +5,8 @@
// remove chickenpk.
#define NUM_KINDS 15 /* 有多少種動物 */
+#define CHICKENLOG "etc/chicken"
+
static const char * const cage[17] = {
"誕生", "週歲", "幼年", "少年", "青春", "青年",
@@ -83,28 +85,84 @@ static const short time_change[NUM_KINDS][14] =
{1, 1, 80, 2, 9, 10, 2, 5, 7, 8, 12, 1, 135, 5},
};
-int
-reload_chicken(void)
+static void time_diff(chicken_t * thechicken);
+static int isdeadth(const chicken_t * thechicken, chicken_t *mychicken);
+
+chicken_t * load_live_chicken(const char *uid)
{
- userec_t xuser;
- chicken_t *mychicken = &cuser.mychicken;
+ char fn[PATHLEN];
+ int fd = 0;
+ chicken_t *p = NULL;
+
+ if (!uid || !uid[0]) return NULL;
+ sethomefile(fn, uid, FN_CHICKEN);
+ if (!dashf(fn)) return NULL;
+ fd = open(fn, O_RDWR);
+ if (fd < 0) return NULL;
+
+ // now fd is valie. open and mmap.
+ p = mmap(NULL, sizeof(chicken_t), PROT_READ|PROT_WRITE, MAP_SHARED,
+ fd, 0);
+ close(fd);
+ return p;
+}
- passwd_query(usernum, &xuser);
- memcpy(mychicken, &xuser.mychicken, sizeof(chicken_t));
- if (!mychicken->name[0])
- return 0;
- else
+int load_chicken(const char *uid, chicken_t *mychicken)
+{
+ char fn[PATHLEN];
+ int fd = 0;
+
+ memset(mychicken, 0, sizeof(chicken_t));
+ if (!uid || !uid[0]) return 0;
+ sethomefile(fn, uid, FN_CHICKEN);
+ if (!dashf(fn)) return 0;
+ fd = open(fn, O_RDONLY);
+ if (fd < 0) return 0;
+ if (read(fd, mychicken, sizeof(chicken_t)) > 0 && mychicken->name[0])
return 1;
+ return 0;
}
-#define CHICKENLOG "etc/chicken"
+void free_live_chicken(chicken_t *p)
+{
+ if (!p) return;
+ munmap(p, sizeof(chicken_t));
+}
+
+void
+chicken_query(const char *userid)
+{
+ chicken_t xchicken;
+ if (!load_chicken(userid, &xchicken))
+ {
+ move(1, 0);
+ clrtobot();
+ prints("\n\n%s 並沒有養寵物..", userid);
+ } else {
+ time_diff(&xchicken);
+ if (!isdeadth(&xchicken, NULL))
+ {
+ show_chicken_data(&xchicken, NULL);
+ prints("\n\n以上是 %s 的寵物資料..", userid);
+ } else {
+ move(1, 0);
+ clrtobot();
+ prints("\n\n%s 的寵物死掉了...", userid);
+ }
+ }
+
+ pressanykey();
+}
static int
new_chicken(void)
{
- chicken_t *mychicken = &cuser.mychicken;
- int price, i;
- char tmp_name[sizeof(mychicken->name)];
+ chicken_t mychicken;
+ int price, i;
+ int fd;
+ char fn[PATHLEN];
+
+ memset(&mychicken, 0, sizeof(chicken_t));
clear();
move(2, 0);
@@ -127,41 +185,53 @@ new_chicken(void)
if (i < 0 || i > NUM_KINDS - 1)
return 0;
- mychicken->type = i;
+ mychicken.type = i;
reload_money();
- price = egg_price[(int)mychicken->type];
+ price = egg_price[(int)mychicken.type];
if (cuser.money < price) {
vmsgf("錢不夠買蛋蛋,蛋蛋要 %d 元", price);
return 0;
}
vice(price, "寵物蛋");
- strlcpy(tmp_name, mychicken->name, sizeof(tmp_name));
- while (strlen(tmp_name) < 3)
- getdata(8, 0, "幫牠取個好名字:", tmp_name,
- sizeof(tmp_name), DOECHO);
- strlcpy(mychicken->name, tmp_name, sizeof(mychicken->name));
+ while (strlen(mychicken.name) < 3)
+ getdata(8, 0, "幫牠取個好名字:", mychicken.name,
+ sizeof(mychicken.name), DOECHO);
+
+ mychicken.lastvisit = mychicken.birthday = mychicken.cbirth = now;
+ mychicken.food = 0;
+ mychicken.weight = time_change[(int)mychicken.type][WEIGHT] / 3;
+ mychicken.clean = 0;
+ mychicken.run = time_change[(int)mychicken.type][RUN];
+ mychicken.attack = time_change[(int)mychicken.type][ATTACK];
+ mychicken.book = time_change[(int)mychicken.type][BOOK];
+ mychicken.happy = time_change[(int)mychicken.type][HAPPY];
+ mychicken.satis = time_change[(int)mychicken.type][SATIS];
+ mychicken.temperament = time_change[(int)mychicken.type][TEMPERAMENT];
+ mychicken.tiredstrong = 0;
+ mychicken.sick = 0;
+ mychicken.hp = time_change[(int)mychicken.type][WEIGHT];
+ mychicken.hp_max = time_change[(int)mychicken.type][WEIGHT];
+ mychicken.mm = 0;
+ mychicken.mm_max = 0;
+
+ // flush it
+ setuserfile(fn, FN_CHICKEN);
+ fd = open(fn, O_WRONLY|O_CREAT, 0666);
+ if (fd < 0)
+ {
+ vmsg("系統錯誤: 無法建立資料,請至 " GLOBAL_BUGREPORT " 報告。");
+ return 0;
+ }
+
+ write(fd, &mychicken, sizeof(chicken_t));
+ close(fd);
+ // log data
log_filef(CHICKENLOG, LOG_CREAT,
ANSI_COLOR(31) "%s " ANSI_RESET "養了一隻叫" ANSI_COLOR(33) " %s " ANSI_RESET "的 "
ANSI_COLOR(32) "%s" ANSI_RESET " 於 %s\n", cuser.userid,
- mychicken->name, chicken_type[(int)mychicken->type], ctime4(&now));
- mychicken->lastvisit = mychicken->birthday = mychicken->cbirth = now;
- mychicken->food = 0;
- mychicken->weight = time_change[(int)mychicken->type][WEIGHT] / 3;
- mychicken->clean = 0;
- mychicken->run = time_change[(int)mychicken->type][RUN];
- mychicken->attack = time_change[(int)mychicken->type][ATTACK];
- mychicken->book = time_change[(int)mychicken->type][BOOK];
- mychicken->happy = time_change[(int)mychicken->type][HAPPY];
- mychicken->satis = time_change[(int)mychicken->type][SATIS];
- mychicken->temperament = time_change[(int)mychicken->type][TEMPERAMENT];
- mychicken->tiredstrong = 0;
- mychicken->sick = 0;
- mychicken->hp = time_change[(int)mychicken->type][WEIGHT];
- mychicken->hp_max = time_change[(int)mychicken->type][WEIGHT];
- mychicken->mm = 0;
- mychicken->mm_max = 0;
+ mychicken.name, chicken_type[(int)mychicken.type], ctime4(&now));
return 1;
}
@@ -177,10 +247,10 @@ show_chicken_stat(const chicken_t * thechicken, int age)
" 體:" ANSI_COLOR(33) "%5d/%-5d" ANSI_RESET " 法:" ANSI_COLOR(33) "%5d/%-5d" ANSI_RESET " 攻擊力:"
ANSI_COLOR(33) "%-7d" ANSI_RESET " 敏捷 :" ANSI_COLOR(33) "%-7d" ANSI_RESET " 知識 :" ANSI_COLOR(33) "%-7d"
ANSI_RESET " \n"
- " 快樂 :" ANSI_COLOR(33) "%-7d" ANSI_RESET " 滿意 :" ANSI_COLOR(33) "%-7d" ANSI_RESET " 疲勞 :"
+ " 快樂 :" ANSI_COLOR(33) "%-7d " ANSI_RESET " 滿意 :" ANSI_COLOR(33) "%-7d " ANSI_RESET " 疲勞 :"
ANSI_COLOR(33) "%-7d" ANSI_RESET " 氣質 :" ANSI_COLOR(33) "%-7d " ANSI_RESET "體重 :"
ANSI_COLOR(33) "%-5.2f" ANSI_RESET " \n"
- " 病氣 :" ANSI_COLOR(33) "%-7d" ANSI_RESET " 乾淨 :" ANSI_COLOR(33) "%-7d" ANSI_RESET " 食物 :"
+ " 病氣 :" ANSI_COLOR(33) "%-7d " ANSI_RESET " 乾淨 :" ANSI_COLOR(33) "%-7d " ANSI_RESET " 食物 :"
ANSI_COLOR(33) "%-7d" ANSI_RESET " 大補丸:" ANSI_COLOR(33) "%-7d" ANSI_RESET " 藥品 :" ANSI_COLOR(33) "%-7d"
ANSI_RESET " \n",
thechicken->name, chicken_type[(int)thechicken->type],
@@ -268,9 +338,8 @@ show_chicken_data(chicken_t * thechicken, chicken_t * pkchicken)
}
static void
-ch_eat(void)
+ch_eat(chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
if (mychicken->food) {
mychicken->weight += time_change[(int)mychicken->type][WEIGHT] +
mychicken->hp_max / 5;
@@ -288,9 +357,8 @@ ch_eat(void)
}
static void
-ch_clean(void)
+ch_clean(chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
mychicken->clean = 0;
mychicken->tiredstrong +=
time_change[(int)mychicken->type][TIREDSTRONG] / 3;
@@ -299,11 +367,10 @@ ch_clean(void)
}
static void
-ch_guess(void)
+ch_guess(chicken_t *mychicken)
{
char *guess[3] = {"剪刀", "石頭", "布"}, me, ch, win;
- chicken_t *mychicken = &cuser.mychicken;
mychicken->happy += time_change[(int)mychicken->type][HAPPY] * 1.5;
mychicken->satis += time_change[(int)mychicken->type][SATIS];
mychicken->tiredstrong += time_change[(int)mychicken->type][TIREDSTRONG];
@@ -325,9 +392,8 @@ ch_guess(void)
}
static void
-ch_book(void)
+ch_book(chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
mychicken->book += time_change[(int)mychicken->type][BOOK];
mychicken->tiredstrong += time_change[(int)mychicken->type][TIREDSTRONG];
show_file(CHICKEN_PIC "/read", 5, 14, NO_RELOAD);
@@ -335,9 +401,8 @@ ch_book(void)
}
static void
-ch_kiss(void)
+ch_kiss(chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
mychicken->happy += time_change[(int)mychicken->type][HAPPY];
mychicken->satis += time_change[(int)mychicken->type][SATIS];
mychicken->tiredstrong +=
@@ -347,9 +412,8 @@ ch_kiss(void)
}
static void
-ch_hit(void)
+ch_hit(chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
mychicken->attack += time_change[(int)mychicken->type][ATTACK];
mychicken->run += time_change[(int)mychicken->type][RUN];
mychicken->mm_max += time_change[(int)mychicken->type][MM_MAX] / 15;
@@ -395,9 +459,8 @@ ch_buyitem(int money, const char *picture, int *item, int haveticket)
}
static void
-ch_eatoo(void)
+ch_eatoo(chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
if (mychicken->oo > 0) {
mychicken->oo--;
mychicken->tiredstrong = 0;
@@ -409,9 +472,8 @@ ch_eatoo(void)
}
static void
-ch_eatmedicine(void)
+ch_eatmedicine(chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
if (mychicken->medicine > 0) {
mychicken->medicine--;
mychicken->sick = 0;
@@ -426,9 +488,8 @@ ch_eatmedicine(void)
}
static void
-ch_kill(void)
+ch_kill(chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
int ans;
ans = getans("棄養要被罰 100 元, 是否要棄養?(y/N)");
@@ -464,7 +525,7 @@ geting_old(int *hp, int *weight, int diff, int age)
}
/* 依時間變動的資料 */
-void
+static void
time_diff(chicken_t * thechicken)
{
int diff;
@@ -549,9 +610,8 @@ time_diff(chicken_t * thechicken)
}
static void
-check_sick(void)
+check_sick(chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
/* 髒病的 */
if (mychicken->tiredstrong > mychicken->hp * 0.3 && mychicken->clean > 150)
mychicken->sick += (mychicken->clean - 150) / 10;
@@ -567,9 +627,8 @@ check_sick(void)
}
static int
-deadtype(const chicken_t * thechicken)
+deadtype(const chicken_t * thechicken, chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
int i;
if (thechicken->hp <= 0) /* hp用盡 */
@@ -592,7 +651,6 @@ deadtype(const chicken_t * thechicken)
ANSI_RESET "掛了 於 %s\n", cuser.userid, thechicken->name,
chicken_type[(int)thechicken->type], ctime4(&now));
mychicken->name[0] = 0;
- passwd_update(usernum, &cuser);
}
return i;
}
@@ -623,20 +681,19 @@ showdeadth(int type)
return type;
}
-int
-isdeadth(const chicken_t * thechicken)
+static int
+isdeadth(const chicken_t * thechicken, chicken_t *mychicken)
{
int i;
- if (!(i = deadtype(thechicken)))
+ if (!(i = deadtype(thechicken, mychicken)))
return 0;
return showdeadth(i);
}
static void
-ch_changename(void)
+ch_changename(chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
char newname[20] = "";
getdata_str(b_lines - 1, 0, "嗯..改個好名字吧:", newname, 18, DOECHO,
@@ -653,9 +710,8 @@ ch_changename(void)
}
static int
-select_menu(int age)
+select_menu(int age, chicken_t *mychicken)
{
- chicken_t *mychicken = &cuser.mychicken;
char ch;
reload_money();
@@ -681,37 +737,37 @@ select_menu(int age)
do {
switch (ch = igetch()) {
case '1':
- ch_clean();
- check_sick();
+ ch_clean(mychicken);
+ check_sick(mychicken);
break;
case '2':
- ch_eat();
- check_sick();
+ ch_eat(mychicken);
+ check_sick(mychicken);
break;
case '3':
- ch_guess();
- check_sick();
+ ch_guess(mychicken);
+ check_sick(mychicken);
break;
case '4':
- ch_book();
- check_sick();
+ ch_book(mychicken);
+ check_sick(mychicken);
break;
case '5':
- ch_kiss();
+ ch_kiss(mychicken);
break;
case '6':
- ch_hit();
- check_sick();
+ ch_hit(mychicken);
+ check_sick(mychicken);
break;
case '7':
ch_buyitem(food_price[(int)mychicken->type], CHICKEN_PIC "/food",
&mychicken->food, 1);
break;
case '8':
- ch_eatoo();
+ ch_eatoo(mychicken);
break;
case '9':
- ch_eatmedicine();
+ ch_eatmedicine(mychicken);
break;
case 'O':
case 'o':
@@ -723,11 +779,11 @@ select_menu(int age)
break;
case 'N':
case 'n':
- ch_changename();
+ ch_changename(mychicken);
break;
case 'K':
case 'k':
- ch_kill();
+ ch_kill(mychicken);
return 0;
case 'Q':
case 'q':
@@ -787,7 +843,6 @@ recover_chicken(chicken_t * thechicken)
bell();
igetch();
thechicken->lastvisit = 0;
- passwd_update(usernum, &cuser);
return 0;
}
@@ -796,24 +851,42 @@ recover_chicken(chicken_t * thechicken)
int
chicken_main(void)
{
- chicken_t *mychicken = &cuser.mychicken;
int age;
+ chicken_t *mychicken = load_live_chicken(cuser.userid);
+
lockreturn0(CHICKEN, LOCK_MULTI);
- reload_chicken();
- if (!mychicken->name[0] && !recover_chicken(mychicken) && !new_chicken()) {
- unlockutmpmode();
- return 0;
+ if (mychicken && !mychicken->name[0])
+ {
+ // possible for recovery
+ recover_chicken(mychicken);
+ }
+ if (!mychicken || !mychicken->name[0])
+ {
+ free_live_chicken(mychicken);
+ mychicken = NULL;
+
+ // create new?
+ if (new_chicken())
+ mychicken = load_live_chicken(cuser.userid);
+
+ // exit if still no valid data.
+ if (!mychicken || !mychicken->name[0])
+ {
+ unlockutmpmode();
+ free_live_chicken(mychicken);
+ return 0;
+ }
}
+ assert(mychicken);
age = ((now - mychicken->cbirth) / (60 * 60 * 24));
do {
time_diff(mychicken);
- if (isdeadth(mychicken))
+ if (isdeadth(mychicken, mychicken))
break;
show_chicken_data(mychicken, NULL);
- } while (select_menu(age));
- reload_money();
- passwd_update(usernum, &cuser);
+ } while (select_menu(age, mychicken));
unlockutmpmode();
+ free_live_chicken(mychicken);
return 0;
}
@@ -821,24 +894,24 @@ chicken_main(void)
int
chickenpk(int fd)
{
- chicken_t *mychicken = &cuser.mychicken;
+ chicken_t *mychicken = load_live_chicken(cuser.userid);
+ chicken_t *ochicken = load_live_chicken(currutmp->mateid);
+
char mateid[IDLEN + 1], data[200], buf[200];
int ch = 0;
userinfo_t *uin = &SHM->uinfo[currutmp->destuip];
- userec_t ouser;
- chicken_t *ochicken = &ouser.mychicken;
int r, attmax, i, datac, duid = currutmp->destuid, catched = 0,
count = 0;
lockreturn0(CHICKEN, LOCK_MULTI);
-
- strlcpy(mateid, currutmp->mateid, sizeof(mateid));
/* 把對手的id用local buffer記住 */
+ strlcpy(mateid, currutmp->mateid, sizeof(mateid));
- getuser(mateid, &ouser);
- reload_chicken();
- if (!ochicken->name[0] || !mychicken->name[0]) {
+ if (!mychicken || !ochicken ||
+ !ochicken->name[0] || !mychicken->name[0]) {
+ free_live_chicken(mychicken);
+ free_live_chicken(ochicken);
bell();
vmsg("有一方沒有寵物"); /* Ptt:妨止page時把寵物賣掉 */
add_io(0, 0);
@@ -846,13 +919,13 @@ chickenpk(int fd)
unlockutmpmode();
return 0;
}
+
show_chicken_data(ochicken, mychicken);
add_io(fd, 3); /* 把fd加到igetch監視 */
+
while (1) {
r = random();
ch = igetch();
- getuser(mateid, &ouser);
- reload_chicken();
show_chicken_data(ochicken, mychicken);
time_diff(mychicken);
@@ -932,7 +1005,7 @@ chickenpk(int fd)
mychicken->name, ochicken->name);
break;
}
- if (deadtype(ochicken)) {
+ if (deadtype(ochicken, mychicken)) {
char *p = strchr(data, '\n');
if(p) *p = '\0';
strlcpy(buf, data, sizeof(buf));
@@ -942,8 +1015,6 @@ chickenpk(int fd)
move(17, 0);
outs(data + 1);
i = strlen(data) + 1;
- passwd_update(duid, &ouser);
- passwd_update(usernum, &cuser);
send(fd, data, i, 0);
if (data[0] == 'q' || data[0] == 'd')
break;
@@ -956,8 +1027,10 @@ chickenpk(int fd)
add_io(0, 0); /* 把igetch恢復回 */
pressanykey();
close(fd);
- showdeadth(deadtype(mychicken));
+ showdeadth(deadtype(mychicken, mychicken));
unlockutmpmode();
+ free_live_chicken(mychicken);
+ free_live_chicken(ochicken);
return 0;
}
#endif // USE_CHICKEN_PK
diff --git a/mbbsd/talk.c b/mbbsd/talk.c
index 03b73815..751fb897 100644
--- a/mbbsd/talk.c
+++ b/mbbsd/talk.c
@@ -438,26 +438,6 @@ my_kick(userinfo_t * uentp)
pressanykey();
}
-static void
-chicken_query(const char *userid)
-{
- userec_t xuser;
- if (getuser(userid, &xuser)) {
- if (xuser.mychicken.name[0]) {
- time_diff(&(xuser.mychicken));
- if (!isdeadth(&(xuser.mychicken))) {
- show_chicken_data(&(xuser.mychicken), NULL);
- prints("\n\n以上是 %s 的寵物資料..", xuser.userid);
- }
- } else {
- move(1, 0);
- clrtobot();
- prints("\n\n%s 並沒有養寵物..", xuser.userid);
- }
- pressanykey();
- }
-}
-
int
my_query(const char *uident)
{
diff --git a/upgrade/r3968_chicken.c b/upgrade/r3968_chicken.c
new file mode 100644
index 00000000..740f42fe
--- /dev/null
+++ b/upgrade/r3968_chicken.c
@@ -0,0 +1,110 @@
+#include "bbs.h"
+
+// warning: if you changed userec_t, you must use the old version.
+
+typedef struct {
+ unsigned int version; /* version number of this sturcture, we
+ * use revision number of project to denote.*/
+
+ char userid[IDLEN + 1]; /* ID */
+ char realname[20]; /* 真實姓名 */
+ char nickname[24]; /* 暱稱 */
+ char passwd[PASSLEN]; /* 密碼 */
+ char padx;
+ unsigned int uflag; /* 習慣1 , see uflags.h */
+ unsigned int uflag2; /* 習慣2 , see uflags.h */
+ unsigned int userlevel; /* 權限 */
+ unsigned int numlogins; /* 上站次數 */
+ unsigned int numposts; /* 文章篇數 */
+ time4_t firstlogin; /* 註冊時間 */
+ time4_t lastlogin; /* 最近上站時間 */
+ char lasthost[16]; /* 上次上站來源 */
+ int money; /* Ptt幣 */
+ char remoteuser[3]; /* 保留 目前沒用到的 */
+ char proverb; /* 座右銘 (unused) */
+ char email[50]; /* Email */
+ char address[50]; /* 住址 */
+ char justify[REGLEN + 1]; /* 審核資料 */
+ unsigned char month; /* 生日 月 */
+ unsigned char day; /* 生日 日 */
+ unsigned char year; /* 生日 年 */
+ unsigned char sex; /* 性別 */
+ unsigned char state; /* TODO unknown (unused ?) */
+ unsigned char pager; /* 呼叫器狀態 */
+ unsigned char invisible; /* 隱形狀態 */
+ char padxx[2];
+ unsigned int exmailbox; /* 購買信箱數 TODO short 就夠了 */
+ chicken_t mychicken; /* 寵物 */
+ time4_t lastsong; /* 上次點歌時間 */
+ unsigned int loginview; /* 進站畫面 */
+ unsigned char channel; /* TODO unused */
+ char padxxx;
+ unsigned short vl_count; /* 違法記錄 ViolateLaw counter */
+ unsigned short five_win; /* 五子棋戰績 勝 */
+ unsigned short five_lose; /* 五子棋戰績 敗 */
+ unsigned short five_tie; /* 五子棋戰績 和 */
+ unsigned short chc_win; /* 象棋戰績 勝 */
+ unsigned short chc_lose; /* 象棋戰績 敗 */
+ unsigned short chc_tie; /* 象棋戰績 和 */
+ int mobile; /* 手機號碼 */
+ char mind[4]; /* 心情 not a null-terminate string */
+ unsigned short go_win; /* 圍棋戰績 勝 */
+ unsigned short go_lose; /* 圍棋戰績 敗 */
+ unsigned short go_tie; /* 圍棋戰績 和 */
+ char pad0[5]; /* 從前放 ident 身份證字號,現在可以拿來做別的事了,
+ 不過最好記得要先清成 0 */
+ unsigned char signature; /* 慣用簽名檔 */
+
+ unsigned char goodpost; /* 評價為好文章數 */
+ unsigned char badpost; /* 評價為壞文章數 */
+ unsigned char goodsale; /* 競標 好的評價 */
+ unsigned char badsale; /* 競標 壞的評價 */
+ char myangel[IDLEN+1]; /* 我的小天使 */
+ char pad2;
+ unsigned short chess_elo_rating; /* 象棋等級分 */
+ unsigned int withme; /* 我想找人下棋,聊天.... */
+ time4_t timeremovebadpost; /* 上次刪除劣文時間 */
+ time4_t timeviolatelaw; /* 被開罰單時間 */
+ char pad[28];
+} old_userec_t;
+
+int main()
+{
+ FILE *fp = fopen(FN_PASSWD, "rb"), *fp2 = NULL;
+ char fn[PATHLEN];
+ old_userec_t u;
+
+ if (!fp) {
+ printf("cannot load password file. abort.\n");
+ return -1;
+ }
+
+ while (fread(&u, sizeof(u), 1, fp) > 0)
+ {
+ if (!u.userid[0])
+ continue;
+ if (!u.mychicken.name[0])
+ continue;
+
+ // now, write this data to user home.
+ // sethomefile(fn, u.userid, FN_CHICKEN);
+ sprintf(fn, BBSHOME "/home/%c/%s/" FN_CHICKEN,
+ u.userid[0], u.userid);
+ fp2 = fopen(fn, "wb");
+ if (!fp2)
+ {
+ printf("ERROR: cannot create chicken data: %s.\n", u.userid);
+ continue;
+ }
+ if (fwrite(&u.mychicken, sizeof(u.mychicken), 1, fp2) < 1)
+ {
+ printf("ERROR: cannot write chicken data: %s.\n", u.userid);
+ unlink(fn);
+ }
+ else
+ printf("Transferred chicken data OK: %s.\n", u.userid);
+ fclose(fp2); fp2 = NULL;
+ }
+ fclose(fp);
+ return 0;
+}