diff options
-rw-r--r-- | docs/FAQ | 10 | ||||
-rw-r--r-- | include/modes.h | 13 | ||||
-rw-r--r-- | include/perm.h | 7 | ||||
-rw-r--r-- | include/proto.h | 16 | ||||
-rw-r--r-- | include/pttstruct.h | 19 | ||||
-rw-r--r-- | mbbsd/brc.c | 19 | ||||
-rw-r--r-- | mbbsd/friend.c | 2 | ||||
-rw-r--r-- | mbbsd/io.c | 35 | ||||
-rw-r--r-- | mbbsd/mail.c | 6 | ||||
-rw-r--r-- | mbbsd/mbbsd.c | 20 | ||||
-rw-r--r-- | mbbsd/menu.c | 12 | ||||
-rw-r--r-- | mbbsd/screen.c | 6 | ||||
-rw-r--r-- | mbbsd/stuff.c | 40 | ||||
-rw-r--r-- | mbbsd/talk.c | 309 | ||||
-rw-r--r-- | mbbsd/user.c | 58 | ||||
-rw-r--r-- | mbbsd/var.c | 15 | ||||
-rw-r--r-- | sample/pttbbs.conf | 3 | ||||
-rw-r--r-- | util/Makefile | 5 | ||||
-rw-r--r-- | util/bbsmail.c | 2 | ||||
-rw-r--r-- | util/r2014convert.c | 63 |
20 files changed, 577 insertions, 83 deletions
@@ -119,11 +119,7 @@ Mbbsmail, P=/home/bbs/bin/bbsmail, F=lsSDFMhPu, U=bbs, S=10,R=20/40, LDFLAGS+= -liconv -L/usr/local/lib 在 Linux 還境下 libiconv 被包含在 libc 中, 所以 -liconv 是不需要的 -請將 pttbbs.mk 中 (line 10) - PTT_LIBS= -lcrypt -lhz -liconv -改成: - PTT_LIBS= -lcrypt -lhz -並將 innbbsd/Makefile 的 LDFLAGS (line 43) +請將 innbbsd/Makefile 的 LDFLAGS (line 43) LDFLAGS+= -liconv 刪除 @@ -136,9 +132,9 @@ Ptt 支援繁體中文轉簡體中文與 UTF-8 的功能 package libhz0 in Debian/Linux ) 若不想開啟此選項 請修改 pttbbs.mk (line 10) - PTT_LIBS= -lcrypt -lhz -liconv + PTT_LIBS= -lcrypt -lhz 改成: - PTT_LIBS= -lcrypt -liconv + PTT_LIBS= -lcrypt ------------------------------------------------------------------------------ 9. 如何讓用 ssh方式進 bbs不用密碼 diff --git a/include/modes.h b/include/modes.h index 8c06317a..a2de94a0 100644 --- a/include/modes.h +++ b/include/modes.h @@ -156,4 +156,17 @@ enum {STRIP_ALL = 0, ONLY_COLOR, NO_RELOAD}; #define SIG_CHC 4 #define SIG_DARK 5 +/* talk.c 中的模式 */ +#define WATERBALL_GENERAL 0 +#define WATERBALL_PREEDIT 1 +#define WATERBALL_ALOHA 2 +#define WATERBALL_SYSOP 3 +#define WATERBALL_CONFIRM 4 +#ifdef PLAY_ANGEL +#define WATERBALL_ANGEL 5 +#define WATERBALL_ANSWER 6 +#define WATERBALL_CONFIRM_ANGEL 7 +#define WATERBALL_CONFIRM_ANSWER 8 +#endif + #endif diff --git a/include/perm.h b/include/perm.h index 02c03d0f..d2788a59 100644 --- a/include/perm.h +++ b/include/perm.h @@ -20,7 +20,12 @@ #define PERM_BBSADM 000000100000 /* BBSADM */ #define PERM_NOTOP 000000200000 /* 不列入排行榜 */ #define PERM_VIOLATELAW 000000400000 /* 違法通緝中 */ -#define PERM_NOOUTMAIL 000001000000 /* 不接受站外的信 */ + +#ifdef PLAY_ANGEL +#define PERM_ANGEL 000001000000 /* 有資格擔任小天使 */ +#endif +#define OLD_PERM_NOOUTMAIL 000001000000 /* 不接受站外的信 */ + #define PERM_NOREGCODE 000002000000 /*不允許認證碼註冊*/ #define PERM_VIEWSYSOP 000004000000 /* 視覺站長 */ #define PERM_LOGUSER 000010000000 /* 觀察使用者行蹤 */ diff --git a/include/proto.h b/include/proto.h index 206593cb..a3e6c557 100644 --- a/include/proto.h +++ b/include/proto.h @@ -456,7 +456,7 @@ char *genpasswd(char *pw); /* screen */ void mouts(int y, int x, char *str); void move(int y, int x); -void outs(char *str); +void outs(const char *str); void clrtoeol(void); void clear(void); void refresh(void); @@ -468,13 +468,13 @@ void redoscr(void); void clrtoline(int line); void standout(void); void standend(void); -int edit_outs(char *text); +int edit_outs(const char *text); void outch(unsigned char c); void rscroll(void); void scroll(void); void getyx(int *y, int *x); void initscr(void); -void out_lines(char *str, int line); +void out_lines(const char *str, int line); /* stuff */ #define isprint2(ch) ((ch & 0x80) || isprint(ch)) @@ -541,6 +541,9 @@ int toconnect(char *host, int port); int toread(int fd, void *buf, int len); int towrite(int fd, void *buf, int len); #endif +#ifdef PLAY_ANGEL +void pressanykey_or_callangel(void); +#endif /* syspost */ int post_msg(char* bname, char* title, char *msg, char* author); @@ -582,6 +585,13 @@ int isvisible_uid(int tuid); int friend_stat(userinfo_t *me, userinfo_t * ui); int call_in(userinfo_t *uentp, int fri_stat); int make_connection_to_somebody(userinfo_t *uin, int timeout); +#ifdef PLAY_ANGEL +int t_changeangel(void); +void CallAngel(void); +void SwitchBeingAngel(void); +void SwitchAngelSex(int); +int t_switchangel(void); +#endif /* tmpjack */ int reg_barbq(void); diff --git a/include/pttstruct.h b/include/pttstruct.h index f3f98de9..7a419c42 100644 --- a/include/pttstruct.h +++ b/include/pttstruct.h @@ -119,6 +119,16 @@ typedef struct userec_t { #define FAVNEW_FLAG 0x20 /* true if add new board into one's fav */ #define FOREIGN 0x100 /* true if a foreign */ #define LIVERIGHT 0x200 /* true if get "liveright" already */ +#define REJ_OUTTAMAIL 0x400 /* true if don't accept outside mails */ +#define REJECT_OUTTAMAIL (cuser.uflag2 & REJ_OUTTAMAIL) +#define REJ_QUESTION 0x800 /* true if don't want to be angel for a while */ +#define REJECT_QUESTION (cuser.uflag2 & REJ_QUESTION) +#define ANGEL_MASK 0x3000 +#define ANGEL_R_MAEL 0x1000 /* true if reject male */ +#define ANGEL_R_FEMAEL 0x2000 /* true if reject female */ +#define ANGEL_STATUS() ((cuser.uflag2 & ANGEL_MASK) >> 12) +#define ANGEL_SET(X) (cuser.uflag2 = (cuser.uflag2 & ~ANGEL_MASK) | \ + ((X & 3) << 12)) #define BTLEN 48 /* Length of board title */ @@ -234,6 +244,14 @@ typedef struct { #define FAVGMAX 32 /* Max groups of Myfavorite */ #define FAVGSLEN 8 /* Max Length of Description String */ +/* values of msgque_t::msgmode */ +#define MSGMODE_TALK 0 +#define MSGMODE_WRITE 1 +#ifdef PLAY_ANGEL +#define MSGMODE_FROMANGEL 2 +#define MSGMODE_TOANGEL 3 +#endif + typedef struct msgque_t { pid_t pid; char userid[IDLEN + 1]; @@ -250,6 +268,7 @@ typedef struct userinfo_t { unsigned char active; /* When allocated this field is true */ unsigned char invisible; /* Used by cloaking function in Xyz menu */ unsigned char sockactive; /* Used to coordinate talk requests */ + unsigned char angel; unsigned int userlevel; unsigned char mode; /* UL/DL, Talk Mode, Chat Mode, ... */ unsigned char pager; /* pager toggle, YEA, or NA */ diff --git a/mbbsd/brc.c b/mbbsd/brc.c index 7ad5e30c..7ba1f40e 100644 --- a/mbbsd/brc.c +++ b/mbbsd/brc.c @@ -9,7 +9,7 @@ #define BRC_BLOCKSIZE 1024 -#if MAX_BOARD > 32767 || BRC_MAXSIZE > 32767 +#if MAX_BOARD > 65535 || BRC_MAXSIZE > 65535 #error Max number of boards or BRC_MAXSIZE cannot fit in unsighed short, \ please rewrite brc.c #endif @@ -109,13 +109,10 @@ brc_putrecord(char *ptr, char *endp, brcbid_t bid, brcnbrd_t num, const time_t * { char * tmp; if (num > 0 && list[0] > brc_expire_time && - ptr + sizeof(brcbid_t) + sizeof(brcnbrd_t) <= endp) { + ptr + sizeof(brcbid_t) + sizeof(brcnbrd_t) < endp) { if (num > BRC_MAXNUM) num = BRC_MAXNUM; - while (num > 0 && list[num - 1] < brc_expire_time) - num--; /* don't write the times before brc_expire_time */ - if (num == 0) return ptr; *(brcbid_t*)ptr = bid; /* write in bid */ @@ -164,7 +161,6 @@ brc_insert_record(brcbid_t bid, brcnbrd_t num, time_t* list) ptr = brc_findrecord_in(brc_buf, brc_buf + brc_size, bid, &tnum); - /* FIXME: this loop is copied from brc_putrecord() */ while (num > 0 && list[num - 1] < brc_expire_time) num--; /* don't write the times before brc_expire_time */ @@ -172,8 +168,9 @@ brc_insert_record(brcbid_t bid, brcnbrd_t num, time_t* list) brc_size -= tnum; /* put on the beginning */ - if (num && (new_size = - sizeof(brcbid_t) + sizeof(brcnbrd_t) + num * sizeof(time_t))){ + if (num){ + new_size = sizeof(brcbid_t) + sizeof(brcnbrd_t) + + num * sizeof(time_t); brc_size += new_size; if (brc_size > brc_alloc && !brc_enlarge_buf()) brc_size = BRC_MAXSIZE; @@ -191,7 +188,7 @@ brc_insert_record(brcbid_t bid, brcnbrd_t num, time_t* list) int sindex = ptr - brc_buf; new_size = sizeof(brcbid_t) + sizeof(brcnbrd_t) + num * sizeof(time_t); - brc_size += new_size - (tmpp - ptr); + brc_size += new_size - len; if (brc_size > brc_alloc) { if (brc_enlarge_buf()) { ptr = brc_buf + sindex; @@ -206,7 +203,7 @@ brc_insert_record(brcbid_t bid, brcnbrd_t num, time_t* list) brc_putrecord(ptr, brc_buf + brc_alloc, bid, num, list); } else { /* deleting record */ memmove(ptr, tmpp, end_size); - brc_size -= (tmpp - ptr); + brc_size -= len; } } @@ -336,6 +333,8 @@ brc_initial_board(const char *boardname) brc_update(); /* write back first */ currbid = getbnum(boardname); + if( currbid == 0 ) + currbid = getbnum(DEFAULT_BOARD); currboard = bcache[currbid - 1].brdname; currbrdattr = bcache[currbid - 1].brdattr; diff --git a/mbbsd/friend.c b/mbbsd/friend.c index eea78bdc..92977969 100644 --- a/mbbsd/friend.c +++ b/mbbsd/friend.c @@ -312,7 +312,7 @@ friend_water(char *message, int type) if ((tuid = searchuser(userid)) && tuid != usernum && (uentp = (userinfo_t *) search_ulist(tuid)) && isvisible_uid(tuid)) - my_write(uentp->pid, message, uentp->userid, 1, NULL); + my_write(uentp->pid, message, uentp->userid, WATERBALL_PREEDIT, NULL); } fclose(fp); } @@ -223,7 +223,6 @@ igetch() else // here is switch for default keys switch (ch) { case IAC: - case '\n': /* filters */ continue; #ifdef DEBUG case Ctrl('Q'):{ @@ -275,7 +274,7 @@ igetch() return (ch); if (currutmp->msgs[0].pid && - WATERMODE(WATER_OFO) && wmofo == -1) { + WATERMODE(WATER_OFO) && wmofo == NOTREPLYING) { int y, x, my_newfd; screenline_t *screen0 = calloc(t_lines, sizeof(screenline_t)); memcpy(screen0, big_picture, t_lines * sizeof(screenline_t)); @@ -315,8 +314,25 @@ igetch() i_newfd = 0; show_call_in(0, 0); watermode = 0; - my_write(currutmp->msgs[0].pid, "水球丟過去 : ", - currutmp->msgs[0].userid, 0, NULL); +#ifndef PLAY_ANGEL + my_write(currutmp->msgs[0].pid, "水球丟過去: ", + currutmp->msgs[0].userid, WATERBALL_GENERAL, NULL); +#else + switch (currutmp->msgs[0].msgmode) { + case MSGMODE_WRITE: + my_write(currutmp->msgs[0].pid, "水球丟過去: ", + currutmp->msgs[0].userid, WATERBALL_GENERAL, NULL); + break; + case MSGMODE_FROMANGEL: + my_write(currutmp->msgs[0].pid, "再問他一次: ", + currutmp->msgs[0].userid, WATERBALL_ANGEL, NULL); + break; + case MSGMODE_TOANGEL: + my_write(currutmp->msgs[0].pid, "回答小主人: ", + currutmp->msgs[0].userid, WATERBALL_ANSWER, NULL); + break; + } +#endif i_newfd = my_newfd; /* 還原螢幕 */ @@ -327,7 +343,8 @@ igetch() continue; } } - return ch; + return ch; + case Ctrl('T'): if (WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW)) { if (watermode > 0) { @@ -373,7 +390,13 @@ igetch() continue; } } - return ch; + return ch; + + case Ctrl('J'): /* Ptt 把 \n 拿掉 */ +#ifdef PLAY_ANGEL + CallAngel(); +#endif + continue; default: return ch; diff --git a/mbbsd/mail.c b/mbbsd/mail.c index 731f37cf..b8da8226 100644 --- a/mbbsd/mail.c +++ b/mbbsd/mail.c @@ -779,7 +779,7 @@ mailtitle() prints("[←]離開[↑↓]選擇[→]閱\讀信件 [R]回信 [x]轉達 " "[y]群組回信 [O]站外信:%s [h]求助\n\033[7m" "編號 日 期 作 者 信 件 標 題 \033[32m", - HAS_PERM(PERM_NOOUTMAIL) ? "\033[31m關\033[m" : "開"); + REJECT_OUTTAMAIL ? "\033[31m關\033[m" : "開"); buf[0] = 0; if (mailsumlimit) { snprintf(buf, sizeof(buf), @@ -971,7 +971,7 @@ mail_edit(int ent, fileheader_t * fhdr, char *direct) static int mail_nooutmail(int ent, fileheader_t * fhdr, char *direct) { - cuser.userlevel ^= PERM_NOOUTMAIL; + cuser.uflag2 ^= REJ_OUTTAMAIL; passwd_update(usernum, &cuser); return TITLE_REDRAW; @@ -1233,7 +1233,7 @@ mail_waterball(int ent, fileheader_t * fhdr, char *direct) } if (invalidaddr(address)) return -2; - if( strstr(address, ".bbs") && HAS_PERM(PERM_NOOUTMAIL) ){ + if( strstr(address, ".bbs") && REJECT_OUTTAMAIL ){ move(b_lines - 4, 0); outs("\n您必須要打開接受站外信, 水球整理系統才能寄入結果\n" "請麻煩到【郵件選單】按大寫 O改成接受站外信 (在右上角)\n" diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c index 47b9fd4a..529f0931 100644 --- a/mbbsd/mbbsd.c +++ b/mbbsd/mbbsd.c @@ -241,6 +241,12 @@ void show_call_in(int save, int which) { char buf[200]; +#ifdef PLAY_ANGEL + if (currutmp->msgs[which].msgmode == MSGMODE_TOANGEL) + snprintf(buf, sizeof(buf), "\033[1;37;46m★%s\033[37;45m %s \033[m", + currutmp->msgs[which].userid, currutmp->msgs[which].last_call_in); + else +#endif snprintf(buf, sizeof(buf), "\033[1;33;46m★%s\033[37;45m %s \033[m", currutmp->msgs[which].userid, currutmp->msgs[which].last_call_in); move(b_lines, 0); @@ -284,7 +290,12 @@ add_history(msgque_t * msg) add_history_water(&water[0], msg); if (WATERMODE(WATER_NEW) || WATERMODE(WATER_OFO)) { for (i = 0; i < 5 && swater[i]; i++) - if (swater[i]->pid == msg->pid) + if (swater[i]->pid == msg->pid +#ifdef PLAY_ANGEL + && swater[i]->msg[0].msgmode == msg->msgmode + /* When throwing waterball to angel directly */ +#endif + ) break; if (i == 5) { waterinit = 1; @@ -766,6 +777,11 @@ setup_utmp(int mode) #endif if (enter_uflag & CLOAK_FLAG) uinfo.invisible = YEA; + + if (REJECT_QUESTION) + uinfo.angel = 1; + uinfo.angel |= ANGEL_STATUS() << 1; + getnewutmpent(&uinfo); SHM->UTMPneedsort = 1; if (!(cuser.numlogins % 20) && cuser.userlevel & PERM_BM) @@ -982,7 +998,7 @@ do_aloha(char *hello) userinfo_t *uentp; if ((uentp = (userinfo_t *) search_ulist_userid(userid)) && isvisible(uentp, currutmp)) { - my_write(uentp->pid, genbuf, uentp->userid, 2, NULL); + my_write(uentp->pid, genbuf, uentp->userid, WATERBALL_ALOHA, NULL); } } fclose(fp); diff --git a/mbbsd/menu.c b/mbbsd/menu.c index 7e3ec37a..38a5801f 100644 --- a/mbbsd/menu.c +++ b/mbbsd/menu.c @@ -272,6 +272,9 @@ domenu(int cmdmode, char *cmdtitle, int cmd, commands_t cmdtable[]) while (++i <= total) if (cmdtable[i].desc[1] == cmd) break; + if (cmd == 'H' && i > total){ + /* TODO: Add menu help */ + } } if (i > total || !HAS_PERM(cmdtable[i].level)) @@ -344,6 +347,9 @@ static commands_t talklist[] = { {t_talk, PERM_PAGE, "TTalk 找人聊聊"}, {t_chat, PERM_CHAT, "CChat 找家茶坊喫茶去"}, {t_display, 0, "DDisplay 顯示上幾次熱訊"}, +#ifdef PLAY_ANGEL + {t_changeangel, PERM_BASIC, "UAChange Angel 更換小天使"}, +#endif {NULL, 0, NULL} }; @@ -373,7 +379,7 @@ static commands_t namelist[] = { static commands_t userlist[] = { {u_info, PERM_LOGINOK, "IInfo 設定個人資料與密碼"}, {calendar, PERM_LOGINOK, "CCalendar 個人行事曆"}, - {u_editcalendar, PERM_LOGINOK, "CDEditCalendar 編輯個人行事曆"}, + {u_editcalendar, PERM_LOGINOK, "CDEditCalendar 編輯個人行事曆"}, {u_loginview, PERM_LOGINOK, "LLogin View 選擇進站畫面"}, {u_ansi, 0, "AANSI 切換 ANSI \033[36m彩\033[35m色\033[37m/" "\033[30;47m黑\033[1;37m白\033[m模示"}, @@ -384,9 +390,9 @@ static commands_t userlist[] = { {u_editplan, PERM_LOGINOK, "QQueryEdit 編輯名片檔"}, {u_editsig, PERM_LOGINOK, "SSignature 編輯簽名檔"}, #if HAVE_FREECLOAK - {u_cloak, PERM_LOGINOK, "KKCloak 隱身術"}, + {u_cloak, PERM_LOGINOK, "KKCloak 隱身術"}, #else - {u_cloak, PERM_CLOAK, "KKCloak 隱身術"}, + {u_cloak, PERM_CLOAK, "KKCloak 隱身術"}, #endif {u_register, PERM_BASIC, "RRegister 填寫《註冊申請單》"}, {u_list, PERM_SYSOP, "UUsers 列出註冊名單"}, diff --git a/mbbsd/screen.c b/mbbsd/screen.c index dcfafe2e..04dcec40 100644 --- a/mbbsd/screen.c +++ b/mbbsd/screen.c @@ -394,7 +394,7 @@ outc(unsigned char ch) } int -edit_outs(char *text) +edit_outs(const char *text) { register int column = 0; register char ch; @@ -405,7 +405,7 @@ edit_outs(char *text) } void -outs(char *str) +outs(const char *str) { while (*str) { outc(*str++); @@ -414,7 +414,7 @@ outs(char *str) /* Jaky */ void -out_lines(char *str, int line) +out_lines(const char *str, int line) { while (*str && line) { outc(*str); diff --git a/mbbsd/stuff.c b/mbbsd/stuff.c index f59d8119..9e7e1c5a 100644 --- a/mbbsd/stuff.c +++ b/mbbsd/stuff.c @@ -424,7 +424,33 @@ vmsg_lines(const int lines, const char msg[]) return ch; } -char getans(const char *fmt,...) +#ifdef PLAY_ANGEL +void +pressanykey_or_callangel(){ + int ch; + + outmsg("\033[37;45;1m \033[33m(h)\033[37m 呼叫小天使 " + "● 請按 \033[33m(Space/Return)\033[37m 繼續 ●" + " \033[33m(^T)\033[37m 存暫存檔 \033[m"); + do { + ch = igetch(); + + if (ch == Ctrl('T')) { + capture_screen(); + break; + }else if (ch == 'h' || ch == 'H'){ + CallAngel(); + break; + } + } while ((ch != ' ') && (ch != KEY_LEFT) && (ch != '\r') && (ch != '\n')); + move(b_lines, 0); + clrtoeol(); + refresh(); +} +#endif + +char +getans(const char *fmt,...) { char msg[256]; char ans[5]; @@ -597,10 +623,12 @@ log_user(const char *fmt, ...) "%s: %s %s", cuser.userid, msg, Cdate(&now)); } -int log_file(char *fn, int flag, const char *fmt,...) +int +log_file(char *fn, int flag, const char *fmt,...) { - int fd; - char msg[256], *realmsg; + int fd; + char msg[256]; + const char *realmsg; if( !(flag & LOG_VF) ){ realmsg = fmt; } @@ -638,7 +666,11 @@ show_help(char *helptext[]) else prints(" %s\n", str); } +#ifdef PLAY_ANGEL + pressanykey_or_callangel(); +#else pressanykey(); +#endif } #endif // _BBS_UTIL_C_ diff --git a/mbbsd/talk.c b/mbbsd/talk.c index 6864faf9..e5936862 100644 --- a/mbbsd/talk.c +++ b/mbbsd/talk.c @@ -457,6 +457,11 @@ water_scr(water_t * tw, int which, char type) move(0, 0); prints(" "); move(0, 0); +#ifdef PLAY_ANGEL + if (tw->msg[0].msgmode == MSGMODE_TOANGEL) + prints("\033[0m回答小主人:"); + else +#endif prints("\033[0m反擊 %s:", tw->userid); clrtoeol(); move(0, strlen(tw->userid) + 6); @@ -480,7 +485,7 @@ my_write2(void) if (swater[0] == NULL) return; - wmofo = 0; + wmofo = REPLYING; currstat0 = currstat; c0 = currutmp->chatid[0]; mode0 = currutmp->mode; @@ -551,12 +556,26 @@ my_write2(void) move(0, 0); prints("\033[m"); clrtoeol(); +#ifndef PLAY_ANGEL snprintf(genbuf, sizeof(genbuf), "攻擊 %s:", tw->userid); + i = WATERBALL_CONFIRM; +#else + if (tw->msg[0].msgmode == MSGMODE_WRITE) { + snprintf(genbuf, sizeof(genbuf), "攻擊 %s:", tw->userid); + i = WATERBALL_CONFIRM; + } else if (tw->msg[0].msgmode == MSGMODE_TOANGEL) { + strcpy(genbuf, "回答小主人:"); + i = WATERBALL_CONFIRM_ANSWER; + } else { /* tw->msg[0].msgmode == MSGMODE_FROMANGEL */ + strcpy(genbuf, "再問他一次:"); + i = WATERBALL_CONFIRM_ANGEL; + } +#endif if (!oldgetdata(0, 0, genbuf, msg, - 80 - strlen(tw->userid) - 6, DOECHO)) + 80 - strlen(tw->userid) - 6, DOECHO)) break; - if (my_write(tw->pid, msg, tw->userid, 4, tw->uin)) + if (my_write(tw->pid, msg, tw->userid, i, tw->uin)) strncpy(tw->msg[5].last_call_in, t_last_write, sizeof(tw->msg[5].last_call_in)); break; @@ -566,7 +585,7 @@ my_write2(void) currstat = currstat0; currutmp->chatid[0] = c0; currutmp->mode = mode0; - if (wmofo == RECVINREPLYING){ + if (wmofo == RECVINREPLYING) { wmofo = NOTREPLYING; write_request(0); } @@ -574,10 +593,22 @@ my_write2(void) } /* - * 被呼叫的時機: 1. 丟群組水球 flag = 1 (pre-edit) 2. 回水球 flag = 0 3. - * 上站aloha flag = 2 (pre-edit) 4. 廣播 flag = 3 if SYSOP, otherwise - * flag = 1 (pre-edit) 5. 丟水球 flag = 0 6. my_write2 flag = 4 - * (pre-edit) but confirm + * 被呼叫的時機: + * 1. 丟群組水球 flag = WATERBALL_PREEDIT, 1 (pre-edit) + * 2. 回水球 flag = WATERBALL_GENERAL, 0 + * 3. 上站aloha flag = WATERBALL_ALOHA, 2 (pre-edit) + * 4. 廣播 flag = WATERBALL_SYSOP, 3 if SYSOP + * flag = WATERBALL_PREEDIT, 1 otherwise + * 5. 丟水球 flag = WATERBALL_GENGRAL, 0 + * 6. my_write2 flag = WATERBALL_CONFIRM, 4 (pre-edit but confirm) + * 7. (when defined PLAY_ANGEL) + * 呼叫小天使 flag = WATERBALL_ANGEL, 5 (id = "小天使") + * 8. (when defined PLAY_ANGEL) + * 回答小主人 flag = WATERBALL_ANSWER, 6 (隱藏 id) + * 9. (when defined PLAY_ANGEL) + * 呼叫小天使 flag = WATERBALL_CONFIRM_ANGEL, 7 (pre-edit) + * 10. (when defined PLAY_ANGEL) + * 回答小主人 flag = WATERBALL_CONFIRM_ANSWER, 8 (pre-edit) */ int my_write(pid_t pid, char *prompt, char *id, int flag, userinfo_t * puin) @@ -591,7 +622,7 @@ my_write(pid_t pid, char *prompt, char *id, int flag, userinfo_t * puin) uin = (puin != NULL) ? puin : (userinfo_t *) search_ulist_pid(pid); strlcpy(destid, id, sizeof(destid)); - if (!uin && !(flag == 0 && water_which->count > 0)) { + if (!uin && !(flag == WATERBALL_GENERAL && water_which->count > 0)) { vmsg("糟糕! 對方已落跑了(不在站上)! "); watermode = -1; return 0; @@ -602,7 +633,11 @@ my_write(pid_t pid, char *prompt, char *id, int flag, userinfo_t * puin) ptime = localtime(&now); - if (flag == 0) { + if (flag == WATERBALL_GENERAL +#ifdef PLAY_ANGEL + || flag == WATERBALL_ANGEL || flag == WATERBALL_ANSWER +#endif + ) { /* 一般水球 */ watermode = 0; if (!(len = getdata(0, 0, prompt, msg, 56, DOECHO))) { @@ -626,8 +661,13 @@ my_write(pid_t pid, char *prompt, char *id, int flag, userinfo_t * puin) } strip_ansi(msg, msg, STRIP_ALL); - if (uin && *uin->userid && (flag == 0 || flag == 4)) { - snprintf(buf, sizeof(buf), "丟給 %s : %s [Y/n]?", uin->userid, msg); + if (uin && *uin->userid && + (flag == WATERBALL_GENERAL || flag == WATERBALL_CONFIRM +#ifdef PLAY_ANGEL + || flag == WATERBALL_ANGEL || flag == WATERBALL_ANSWER +#endif + )) { + snprintf(buf, sizeof(buf), "丟給 %s : %s [Y/n]?", destid, msg); getdata(0, 0, buf, genbuf, 3, LCECHO); if (genbuf[0] == 'n') { currutmp->chatid[0] = c0; @@ -638,7 +678,11 @@ my_write(pid_t pid, char *prompt, char *id, int flag, userinfo_t * puin) } } watermode = -1; - if (!uin || !*uin->userid || strcasecmp(destid, uin->userid)) { + if (!uin || !*uin->userid || (strcasecmp(destid, uin->userid) +#ifdef PLAY_ANGEL + && flag != WATERBALL_ANGEL && flag != WATERBALL_CONFIRM_ANGEL +#endif + )) { vmsg("糟糕! 對方已落跑了(不在站上)! "); currutmp->chatid[0] = c0; currutmp->mode = mode0; @@ -646,7 +690,7 @@ my_write(pid_t pid, char *prompt, char *id, int flag, userinfo_t * puin) return 0; } fri_stat = friend_stat(currutmp, uin); - if (flag != 2) { /* aloha 的水球不用存下來 */ + if (flag != WATERBALL_ALOHA) { /* aloha 的水球不用存下來 */ /* 存到自己的水球檔 */ if (!fp_writelog) { sethomefile(genbuf, cuser.userid, fn_writelog); @@ -654,24 +698,37 @@ my_write(pid_t pid, char *prompt, char *id, int flag, userinfo_t * puin) } if (fp_writelog) { fprintf(fp_writelog, "To %s: %s [%s]\n", - uin->userid, msg, Cdatelite(&now)); - snprintf(t_last_write, 66, "To %s: %s", uin->userid, msg); + destid, msg, Cdatelite(&now)); + snprintf(t_last_write, 66, "To %s: %s", destid, msg); } } - if (flag == 3 && uin->msgcount) { + if (flag == WATERBALL_SYSOP && uin->msgcount) { /* 不懂 */ uin->destuip = currutmp - &SHM->uinfo[0]; uin->sig = 2; if (uin->pid > 0) kill(uin->pid, SIGUSR1); - } else if (flag != 2 && + } else if ((flag != WATERBALL_ALOHA && +#ifdef PLAY_ANGEL + flag != WATERBALL_ANGEL && + flag != WATERBALL_ANSWER && + flag != WATERBALL_CONFIRM_ANGEL && + flag != WATERBALL_CONFIRM_ANSWER && + /* Angel accept or not is checked outside. + * Avoiding new users don't know what pager is. */ +#endif !HAS_PERM(PERM_SYSOP) && (uin->pager == 3 || uin->pager == 2 || (uin->pager == 4 && !(fri_stat & HFM)))) +#ifdef PLAY_ANGEL + || ((flag == WATERBALL_ANGEL || flag == WATERBALL_CONFIRM_ANGEL) + && (uin->angel & 1)) +#endif + ) { outmsg("\033[1;33;41m糟糕! 對方防水了! \033[37m~>_<~\033[m"); - else { + } else { int write_pos = uin->msgcount; /* try to avoid race */ if ( write_pos < (MAX_MSGS - 1) ) { /* race here */ unsigned char pager0 = uin->pager; @@ -679,12 +736,34 @@ my_write(pid_t pid, char *prompt, char *id, int flag, userinfo_t * puin) uin->msgcount = write_pos + 1; uin->pager = 2; uin->msgs[write_pos].pid = currpid; - strlcpy(uin->msgs[write_pos].userid, cuser.userid, +#ifdef PLAY_ANGEL + if (flag == WATERBALL_ANSWER || flag == WATERBALL_CONFIRM_ANSWER) + strlcpy(uin->msgs[write_pos].userid, "小天使", sizeof(uin->msgs[write_pos].userid)); + else +#endif + strlcpy(uin->msgs[write_pos].userid, cuser.userid, + sizeof(uin->msgs[write_pos].userid)); strlcpy(uin->msgs[write_pos].last_call_in, msg, sizeof(uin->msgs[write_pos].last_call_in)); +#ifndef PLAY_ANGEL + uin->msgs[write_pos].msgmode = MSGMODE_WRITE; +#else + switch (flag) { + case WATERBALL_ANGEL: + case WATERBALL_CONFIRM_ANGEL: + uin->msgs[write_pos].msgmode = MSGMODE_TOANGEL; + break; + case WATERBALL_ANSWER: + case WATERBALL_CONFIRM_ANSWER: + uin->msgs[write_pos].msgmode = MSGMODE_FROMANGEL; + break; + default: + uin->msgs[write_pos].msgmode = MSGMODE_WRITE; + } +#endif uin->pager = pager0; - } else if (flag != 2) + } else if (flag != WATERBALL_ALOHA) outmsg("\033[1;33;41m糟糕! 對方不行了! (收到太多水球) \033[37m@_@\033[m"); if (uin->msgcount >= 1 && @@ -693,12 +772,21 @@ my_write(pid_t pid, char *prompt, char *id, int flag, userinfo_t * puin) #else (uin->pid <= 0 || kill(uin->pid, SIGUSR2) == -1) #endif - && flag != 2) + && flag != WATERBALL_ALOHA) outmsg("\033[1;33;41m糟糕! 沒打中! \033[37m~>_<~\033[m"); - else if (uin->msgcount == 1 && flag != 2) + else if (uin->msgcount == 1 && flag != WATERBALL_ALOHA) outmsg("\033[1;33;44m水球砸過去了! \033[37m*^o^*\033[m"); - else if (uin->msgcount > 1 && uin->msgcount < MAX_MSGS && flag != 2) + else if (uin->msgcount > 1 && uin->msgcount < MAX_MSGS && + flag != WATERBALL_ALOHA) outmsg("\033[1;33;44m再補上一粒! \033[37m*^o^*\033[m"); + +#if defined(NOKILLWATERBALL) && defined(PLAY_ANGEL) + /* Questioning and answering should better deliver immediately. */ + if ((flag == WATERBALL_ANGEL || flag == WATERBALL_ANSWER || + flag == WATERBALL_CONFIRM_ANGEL || + flag == WATERBALL_CONFIRM_ANSWER) && uin->pid) + kill(uin->pid, SIGUSR2); +#endif } clrtoeol(); @@ -770,8 +858,9 @@ t_display_new(void) } } for (i = 0; i < water_which->count; i++) { - int a = (water_which->top - i - 1 + MAX_REVIEW) % MAX_REVIEW, len = 75 - strlen(water_which->msg[a].last_call_in) - - strlen(water_which->msg[a].userid); + int a = (water_which->top - i - 1 + MAX_REVIEW) % MAX_REVIEW; + int len = 75 - strlen(water_which->msg[a].last_call_in) + - strlen(water_which->msg[a].userid); if (len < 0) len = 0; @@ -1429,7 +1518,11 @@ t_showhelp() outs("(Y) 顯示正在看什麼板\n"); #endif } +#ifdef PLAY_ANGEL + pressanykey_or_callangel(); +#else pressanykey(); +#endif } /* @@ -1849,10 +1942,18 @@ draw_pickup(int drawall, pickup_t * pickup, int pickup_way, int call_in(userinfo_t * uentp, int fri_stat) { +#ifdef PLAY_ANGLE + static int CallInAngelWarning = 1; + if( CallInAngelWarning && ! strcasecmp(uentp->userid, cuser.myangel) ){ + outmsg("直接丟水球給小天使是會被知道 ID 的喔!"); + CallInAngelWarning = 0; + } +#endif + if (iswritable_stat(uentp, fri_stat)) { char genbuf[60]; snprintf(genbuf, sizeof(genbuf), "Call-In %s :", uentp->userid); - my_write(uentp->pid, genbuf, uentp->userid, 0, NULL); + my_write(uentp->pid, genbuf, uentp->userid, WATERBALL_GENERAL, NULL); return 1; } return 0; @@ -2171,7 +2272,7 @@ userlist(void) uentp = SHM->sorted[SHM->currsorted][0][i]; if (uentp->pid && kill(uentp->pid, 0) != -1) my_write(uentp->pid, genbuf, - uentp->userid, 1, NULL); + uentp->userid, WATERBALL_PREEDIT, NULL); if (i % 100 == 0) sleep(1); } @@ -2191,8 +2292,8 @@ userlist(void) uentp->pager != 3 && (uentp->pager != 4 || frstate & HFM) && !(frstate & IRH)) { - my_write(uentp->pid, genbuf, - uentp->userid, 1, NULL); + my_write(uentp->pid, genbuf, uentp->userid, + WATERBALL_PREEDIT, NULL); } } } @@ -2626,6 +2727,7 @@ talkreply(void) strlcpy(currutmp->msgs[0].userid, uip->userid, sizeof(currutmp->msgs[0].userid)); strlcpy(currutmp->msgs[0].last_call_in, "呼叫、呼叫,聽到請回答 (Ctrl-R)", sizeof(currutmp->msgs[0].last_call_in)); + currutmp->msgs[0].msgmode = MSGMODE_TALK; prints("對方來自 [%s],共上站 %d 次,文章 %d 篇\n", uip->from, xuser.numlogins, xuser.numposts); showplans(uip->userid); @@ -2705,3 +2807,150 @@ talkreply(void) * ""); } if (++linecnt < 3){ strcat(uentry, "│"); outs(uentry); } else{ * outs(uentry); linecnt = 0; clrtoeol(); move(++lineno, 0); } return 0; } */ + +#ifdef PLAY_ANGEL +/* 小天使小主人處理函式 */ +int +t_changeangel(){ + char buf[4]; + if( cuser.myangel[0] == 0 ) return 0; + getdata(b_lines - 1, 0, + "更換小天使後就無法換回了喔! 是否要更換小天使? [y/N]", + buf, 3, LCECHO); + if( buf[0] == 'y' || buf[0] == 'Y' ){ + cuser.myangel[0] = 0; + outs("小天使更新完成,下次呼叫時會選出新的小天使"); + } + return XEASY; +} + +static int +FindAngel(void){ + int nAngel; + int i, j; + int choose; + int trial = 0; + int mask; + + if (cuser.sex < 6) /* 正常性別 */ + mask = 1 | (2 << (cuser.sex & 1)); + else + mask = 7; + + do{ + nAngel = 0; + j = SHM->currsorted; + for (i = 0; i < SHM->UTMPnumber; ++i) + if ((SHM->sorted[j][0][i]->userlevel & PERM_ANGEL) + && (SHM->sorted[j][0][j]->angel & mask) == 0) + ++nAngel; + + if (nAngel == 0) + return 0; + + choose = rand() % nAngel + 1; + j = SHM->currsorted; + for (i = 0; i < SHM->UTMPnumber && choose; ++i) + if ((SHM->sorted[j][0][i]->userlevel & PERM_ANGEL) + && (SHM->sorted[j][0][j]->angel & mask) == 0) + --choose; + + if (choose == 0 && SHM->sorted[j][0][i - 1]->uid != currutmp->uid){ + strlcpy(cuser.myangel, SHM->sorted[j][0][i - 1]->userid, IDLEN + 1); + return 1; + } + }while(++trial < 5); + return 0; +} + +static void +NoAngelFound(const char* msg){ + move(b_lines, 0); + outs(msg); + if (currutmp->mode != EDITING) + outs(",請先在新手板上尋找答案或按 Ctrl-P 發問"); + clrtoeol(); + refresh(); + sleep(1); + if (currutmp->mode != EDITING){ + char old_board[IDLEN + 1] = ""; + if (currboard) + strlcpy(old_board, currboard, IDLEN + 1); + + brc_initial_board("PttNewHand"); + Read(); + + if (old_board[0]) + brc_initial_board(old_board); + } + return; +} + +static void +TalkToAngel(){ + userinfo_t* uent; + + if (cuser.myangel[0] == 0 && ! FindAngel()){ + NoAngelFound("現在沒有小天使在線上"); + return; + } + + uent = search_ulist_userid(cuser.myangel); + if (uent == 0 || (uent->angel & 1)){ + NoAngelFound("您的小天使現在不在線上"); + return; + } + + /* 這段話或許可以在小天使回答問題時 show 出來 + move(b_lines - 1, 0); + outs("現在你的id受到保密,回答你問題的小天使並不知道你是誰 \n" + "你可以選擇不向對方透露自己身份來保護自己 "); + */ + + my_write(uent->pid, "問小天使: ", "小天使", WATERBALL_ANGEL, uent); + return; +} + +void +CallAngel(){ + static int entered = 0; + screenline_t *screen0; + int x, y; + + if (entered) + return; + entered = 1; + + screen0 = calloc(t_lines, sizeof(screenline_t)); + getyx(&y, &x); + memcpy(screen0, big_picture, t_lines * sizeof(screenline_t)); + + TalkToAngel(); + + memcpy(big_picture, screen0, t_lines * sizeof(screenline_t)); + move(y, x); + free(screen0); + redoscr(); + + entered = 0; +} + +void +SwitchBeingAngel(){ + cuser.uflag2 ^= REJ_QUESTION; + currutmp->angel ^= 1; +} + +void +SwitchAngelSex(int newmode){ + ANGEL_SET(newmode); + currutmp->angel = (currutmp->angel & ~0x6) | ((newmode & 3) << 1); +} + +int +t_switchangel(){ + SwitchBeingAngel(); + outs(REJECT_QUESTION ? "休息一會兒" : "開放小主人問問題"); + return XEASY; +} +#endif diff --git a/mbbsd/user.c b/mbbsd/user.c index 9227c381..f73a26be 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -89,6 +89,11 @@ user_display(userec_t * u, int real) get_num_records(genbuf, sizeof(fileheader_t)), u->exmailbox, u->mobile, u->month, u->day, u->year % 100, u->mychicken.name); +#ifdef PLAY_ANGEL + if (real) + prints(" 小 天 使: %s\n", + u->myangel[0] ? u->myangel : "無"); +#endif prints(" 註冊日期: %s", ctime(&u->firstlogin)); prints(" 前次光臨: %s", ctime(&u->lastlogin)); prints(" 前次點歌: %s", ctime(&u->lastsong)); @@ -217,7 +222,11 @@ violate_law(userec_t * u, int unum) static void Customize(void) { char done = 0, mindbuf[5]; + int key; char *wm[3] = {"一般", "進階", "未來"}; +#ifdef PLAY_ANGEL + char *am[4] = {"男女皆可", "限女生", "限男生", "暫不接受新的小主人"}; +#endif showtitle("個人化設定", "個人化設定"); memcpy(mindbuf, &currutmp->mind, 4); @@ -228,14 +237,23 @@ static void Customize(void) move(4, 0); prints("%-30s%10s\n", "A. 水球模式", wm[(cuser.uflag2 & WATER_MASK)]); - prints("%-30s%10s\n", "B. 接受站外信", - ((cuser.userlevel & PERM_NOOUTMAIL) ? "否" : "是")); + prints("%-30s%10s\n", "B. 接受站外信", REJECT_OUTTAMAIL ? "否" : "是"); prints("%-30s%10s\n", "C. 新板自動進我的最愛", ((cuser.uflag2 & FAVNEW_FLAG) ? "是" : "否")); prints("%-30s%10s\n", "D. 目前的心情", mindbuf); prints("%-30s%10s\n", "E. 高亮度顯示我的最愛", ((cuser.uflag2 & FAVNOHILIGHT) ? "否" : "是")); - switch(getkey("請按 [A-E] 切換設定,按 [Return] 結束:")){ +#ifdef PLAY_ANGEL + if( HAS_PERM(PERM_ANGEL) ){ + prints("%-30s%10s\n", "F. 開放小主人詢問", + (REJECT_QUESTION ? "否" : "是")); + prints("%-30s%10s\n", "G. 接受的小主人性別", am[ANGEL_STATUS()]); + key = getkey("請按 [A-G] 切換設定,按 [Return] 結束:"); + }else +#endif + key = getkey("請按 [A-e] 切換設定,按 [Return] 結束:"); + + switch (key) { case 'a':{ int currentset = cuser.uflag2 & WATER_MASK; currentset = (currentset + 1) % 3; @@ -245,7 +263,7 @@ static void Customize(void) } break; case 'b': - cuser.userlevel ^= PERM_NOOUTMAIL; + cuser.uflag2 ^= REJ_OUTTAMAIL; break; case 'c': cuser.uflag2 ^= FAVNEW_FLAG; @@ -266,6 +284,23 @@ static void Customize(void) case 'e': cuser.uflag2 ^= FAVNOHILIGHT; break; + +#ifdef PLAY_ANGEL + case 'f': + if( HAS_PERM(PERM_ANGEL) ){ + SwitchBeingAngel(); + break; + } + done = 1; + break; + + case 'g': + if( HAS_PERM(PERM_ANGEL) ){ + SwitchAngelSex(ANGEL_STATUS() + 1); + break; + } +#endif + default: done = 1; } @@ -374,6 +409,21 @@ uinfo_query(userec_t * u, int real, int unum) i++; break; } + +#ifdef PLAY_ANGEL + if (real) + while (1) { + getdata_str(i, 0, "小天使:", buf, IDLEN + 1, DOECHO, + x.myangel); + if(buf[0] == 0 || (getuser(buf) && + (xuser.userlevel & PERM_ANGEL))){ + strlcpy(x.myangel, buf, IDLEN + 1); + ++i; + break; + } + } +#endif + if (real) { int l; if (HAS_PERM(PERM_BBSADM)) { diff --git a/mbbsd/var.c b/mbbsd/var.c index 3ff019f0..c499663b 100644 --- a/mbbsd/var.c +++ b/mbbsd/var.c @@ -21,7 +21,11 @@ char *str_permid[] = { "BBSADM", /* PERM_POSTMARK */ "不列入排行榜", /* PERM_NOTOP */ "違法通緝中", /* PERM_VIOLATELAW */ - "不接受站外的信", /* PERM_ */ +#ifdef PLAY_ANGEL + "可擔任小天使", /* PERM_ANGEL */ +#else + "未使用", +#endif "不允許\認證碼註冊", /* PERM_NOREGCODE */ "視覺站長", /* PERM_VIEWSYSOP */ "觀察使用者行蹤", /* PERM_LOGUSER */ @@ -332,13 +336,14 @@ int automargins = 1; time_t now; int KEY_ESC_arg; int watermode = -1; -int wmofo = -1; +int wmofo = NOTREPLYING; /* * WATERMODE(WATER_ORIG) | WATERMODE(WATER_NEW): * ???????????????????? - * Ptt 水球回顧 e = -1 - * 沒在回水球 = 0 在回上一顆水球 (Ctrl-R) > 0 在回前 n 顆水球 (Ctrl-R - * Ctrl-R) + * Ptt 水球回顧 (FIXME: guessed by scw) + * watermode = -1 沒在回水球 + * = 0 在回上一顆水球 (Ctrl-R) + * > 0 在回前 n 顆水球 (Ctrl-R Ctrl-R) * * WATERMODE(WATER_OFO) by in2 * wmofo = NOTREPLYING 沒在回水球 diff --git a/sample/pttbbs.conf b/sample/pttbbs.conf index a646aa0c..91773abb 100644 --- a/sample/pttbbs.conf +++ b/sample/pttbbs.conf @@ -148,6 +148,9 @@ /* 在轉信時附上的時區. 若在台灣, 中國大陸等地, 用預設的即可. */ //#define INNTIMEZONE "+0800 (CST)" +/* 開啟小天使小主人功能 */ +//#define PLAY_ANGEL + /* 前進站畫面 */ #define INSCREEN \ "前進站畫面 (請至 pttbbs.conf 修改您的前進站畫面)" diff --git a/util/Makefile b/util/Makefile index 99ff62af..04c0d4cc 100644 --- a/util/Makefile +++ b/util/Makefile @@ -97,3 +97,8 @@ installbbsctl: bbsctl cleanpasswd: cleanpasswd.c ${UTIL_OBJS} ${CC} ${CFLAGS} ${LDFLAGS} -o cleanpasswd ${UTIL_OBJS} cleanpasswd.c + +r2014transfer: r2014convert + ${CC} ${CFLAGS} ${LDFLAGS} -o r2014convert r2014convert.c + ./r2014convert + rm r2014convert diff --git a/util/bbsmail.c b/util/bbsmail.c index 2ca997b8..24065ef1 100644 --- a/util/bbsmail.c +++ b/util/bbsmail.c @@ -93,7 +93,7 @@ int mail2bbs(char *userid) return -1;//EX_NOUSER; } - if( xuser.userlevel & PERM_NOOUTMAIL ) + if( xuser.uflag2 & REJ_OUTTAMAIL ) return -1; //不接受站外信 sprintf(filename, BBSHOME "/home/%c/%s", userid[0], userid); diff --git a/util/r2014convert.c b/util/r2014convert.c new file mode 100644 index 00000000..7609cee4 --- /dev/null +++ b/util/r2014convert.c @@ -0,0 +1,63 @@ +#include "bbs.h" + +int main(){ + int orig_fd, new_fd; + userec_t u; + int count = 0; + + orig_fd = open(BBSHOME "/.AngelTrans", O_WRONLY | O_CREAT | O_EXCL, 0600); + if (orig_fd == -1) { + if (errno == EEXIST) { + char c; + printf("It seems your .PASSWD file has been transfered, " + "do it any way?[y/N] "); + fflush(stdout); + scanf(" %c", &c); + if (c != 'y' && c != 'Y') + return 0; + } else { + perror("opening " BBSHOME "/.AngelTrans for marking"); + return 0; + } + } else { + time_t t = time(NULL); + char* str = ctime(&t); + write(orig_fd, str, strlen(str)); + } + + orig_fd = open(BBSHOME "/.PASSWDS", O_RDONLY); + if( orig_fd < 0 ){ + perror("opening " BBSHOME "/.PASSWDS for reading"); + return 1; + } + printf("Reading from " BBSHOME "/.PASSWDS\n"); + + new_fd = open(BBSHOME "/PASSWDS.NEW", O_WRONLY | O_CREAT | O_TRUNC, 0600); + if( new_fd < 0 ){ + perror("opening " BBSHOME "/PASSWDS.NEW for writing"); + return 1; + } + printf("Writing to " BBSHOME "/PASSWDS.NEW\n"); + + while(read(orig_fd, &u, sizeof(userec_t)) == sizeof(userec_t)){ + // clear 0x400, 0x800, and 0x3000 + u.uflag2 &= ~(REJ_OUTTAMAIL | REJ_QUESTION | ANGEL_MASK); + if( u.userlevel & OLD_PERM_NOOUTMAIL ) + u.uflag2 |= REJ_OUTTAMAIL; + u.userlevel &= ~PERM_ANGEL; + bzero(u.myangel, IDLEN + 1); + write(new_fd, &u, sizeof(userec_t)); + ++count; + } + + close(orig_fd); + close(new_fd); + printf("Done, totally %d accounts translated\n", count); + + printf("Moving files....\n"); + system("mv -i " BBSHOME "/.PASSWDS " BBSHOME "/.PASSWDS.old"); + system("mv -i " BBSHOME "/PASSWDS.NEW " BBSHOME "/.PASSWDS"); + printf("Done, old password file is now at " BBSHOME "/.PASSWDS.old\n"); + + return 0; +} |