summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/FAQ10
-rw-r--r--include/modes.h13
-rw-r--r--include/perm.h7
-rw-r--r--include/proto.h16
-rw-r--r--include/pttstruct.h19
-rw-r--r--mbbsd/brc.c19
-rw-r--r--mbbsd/friend.c2
-rw-r--r--mbbsd/io.c35
-rw-r--r--mbbsd/mail.c6
-rw-r--r--mbbsd/mbbsd.c20
-rw-r--r--mbbsd/menu.c12
-rw-r--r--mbbsd/screen.c6
-rw-r--r--mbbsd/stuff.c40
-rw-r--r--mbbsd/talk.c309
-rw-r--r--mbbsd/user.c58
-rw-r--r--mbbsd/var.c15
-rw-r--r--sample/pttbbs.conf3
-rw-r--r--util/Makefile5
-rw-r--r--util/bbsmail.c2
-rw-r--r--util/r2014convert.c63
20 files changed, 577 insertions, 83 deletions
diff --git a/docs/FAQ b/docs/FAQ
index 27c78cd3..8ab34fa8 100644
--- a/docs/FAQ
+++ b/docs/FAQ
@@ -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);
}
diff --git a/mbbsd/io.c b/mbbsd/io.c
index 78adddda..aee1d04a 100644
--- a/mbbsd/io.c
+++ b/mbbsd/io.c
@@ -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;
+}