diff options
Diffstat (limited to 'mbbsd')
-rw-r--r-- | mbbsd/Makefile | 136 | ||||
-rw-r--r-- | mbbsd/admin.c | 1172 | ||||
-rw-r--r-- | mbbsd/aids.c | 290 | ||||
-rw-r--r-- | mbbsd/alloc.c | 254 | ||||
-rw-r--r-- | mbbsd/announce.c | 1558 | ||||
-rw-r--r-- | mbbsd/args.c | 73 | ||||
-rw-r--r-- | mbbsd/assess.c | 268 | ||||
-rw-r--r-- | mbbsd/bbs.c | 3986 | ||||
-rw-r--r-- | mbbsd/bbslua.c | 1801 | ||||
-rw-r--r-- | mbbsd/bbsluaext.c | 83 | ||||
-rw-r--r-- | mbbsd/board.c | 1960 | ||||
-rw-r--r-- | mbbsd/brc.c | 596 | ||||
-rw-r--r-- | mbbsd/cache.c | 1215 | ||||
-rw-r--r-- | mbbsd/cal.c | 630 | ||||
-rw-r--r-- | mbbsd/calendar.c | 362 | ||||
-rw-r--r-- | mbbsd/card.c | 672 | ||||
-rw-r--r-- | mbbsd/chat.c | 597 | ||||
-rw-r--r-- | mbbsd/chc.c | 1012 | ||||
-rw-r--r-- | mbbsd/chc_tab.c | 106 | ||||
-rw-r--r-- | mbbsd/chess.c | 1762 | ||||
-rw-r--r-- | mbbsd/chicken.c | 1138 | ||||
-rw-r--r-- | mbbsd/convert.c | 123 | ||||
-rw-r--r-- | mbbsd/crypt.c | 647 | ||||
-rw-r--r-- | mbbsd/dark.c | 565 | ||||
-rw-r--r-- | mbbsd/edit.c | 3886 | ||||
-rw-r--r-- | mbbsd/emaildb.c | 244 | ||||
-rw-r--r-- | mbbsd/fav.c | 1320 | ||||
-rw-r--r-- | mbbsd/file.c | 186 | ||||
-rw-r--r-- | mbbsd/friend.c | 572 | ||||
-rw-r--r-- | mbbsd/gamble.c | 388 | ||||
-rw-r--r-- | mbbsd/go.c | 1118 | ||||
-rw-r--r-- | mbbsd/gomo.c | 590 | ||||
-rw-r--r-- | mbbsd/guess.c | 369 | ||||
-rw-r--r-- | mbbsd/io.c | 1050 | ||||
-rw-r--r-- | mbbsd/kaede.c | 165 | ||||
-rw-r--r-- | mbbsd/lovepaper.c | 114 | ||||
-rw-r--r-- | mbbsd/mail.c | 2092 | ||||
-rw-r--r-- | mbbsd/mbbsd.c | 1832 | ||||
-rw-r--r-- | mbbsd/menu.c | 718 | ||||
-rw-r--r-- | mbbsd/merge.c | 237 | ||||
-rw-r--r-- | mbbsd/more.c | 77 | ||||
-rw-r--r-- | mbbsd/name.c | 1067 | ||||
-rw-r--r-- | mbbsd/osdep.c | 643 | ||||
-rw-r--r-- | mbbsd/othello.c | 577 | ||||
-rw-r--r-- | mbbsd/passwd.c | 171 | ||||
-rw-r--r-- | mbbsd/pfterm.c | 2502 | ||||
-rw-r--r-- | mbbsd/pmore.c | 3732 | ||||
-rw-r--r-- | mbbsd/random.c | 711 | ||||
-rw-r--r-- | mbbsd/read.c | 1371 | ||||
-rw-r--r-- | mbbsd/record.c | 666 | ||||
-rw-r--r-- | mbbsd/register.c | 3040 | ||||
-rw-r--r-- | mbbsd/reversi.c | 513 | ||||
-rw-r--r-- | mbbsd/screen.c | 819 | ||||
-rw-r--r-- | mbbsd/stuff.c | 828 | ||||
-rw-r--r-- | mbbsd/syspost.c | 146 | ||||
-rw-r--r-- | mbbsd/talk.c | 3654 | ||||
-rw-r--r-- | mbbsd/telnet.c | 338 | ||||
-rw-r--r-- | mbbsd/term.c | 118 | ||||
-rw-r--r-- | mbbsd/time.c | 20 | ||||
-rw-r--r-- | mbbsd/topsong.c | 72 | ||||
-rw-r--r-- | mbbsd/user.c | 1452 | ||||
-rw-r--r-- | mbbsd/var.c | 628 | ||||
-rw-r--r-- | mbbsd/vice.c | 153 | ||||
-rw-r--r-- | mbbsd/vote.c | 1088 | ||||
-rw-r--r-- | mbbsd/voteboard.c | 400 | ||||
-rw-r--r-- | mbbsd/xyz.c | 338 |
66 files changed, 0 insertions, 61011 deletions
diff --git a/mbbsd/Makefile b/mbbsd/Makefile deleted file mode 100644 index a33301c6..00000000 --- a/mbbsd/Makefile +++ /dev/null @@ -1,136 +0,0 @@ -# $Id$ - -SRCROOT= .. -.include "$(SRCROOT)/pttbbs.mk" - -####################################################################### -# common modules -####################################################################### - -PROG= mbbsd -CHESSOBJS= chc.o chc_tab.o chess.o go.o gomo.o dark.o reversi.o -GAMEOBJS = card.o guess.o chicken.o othello.o -SYSOBJS = args.o crypt.o osdep.o -COREOBJS = bbs.o announce.o read.o board.o cache.o brc.o mail.o record.o fav.o -ACCOBJS = user.o register.o passwd.o -TALKOBJS = talk.o chat.o friend.o -NETOBJS = mbbsd.o io.o term.o -UTILOBJS = stuff.o file.o kaede.o convert.o name.o -PLUGOBJS = lovepaper.o calendar.o topsong.o vice.o -OBJS= admin.o assess.o cal.o edit.o menu.o more.o gamble.o \ - xyz.o syspost.o vote.o var.o voteboard.o \ - pmore.o telnet.o \ - $(COREOBJS) $(ACCOBJS) $(NETOBJS) $(TALKOBJS) $(UTILOBJS) \ - $(SYSOBJS) $(PLUGOBJS) $(CHESSOBJS) $(GAMEOBJS) - -####################################################################### -# conditional configurations and optional modules -####################################################################### - -.if !defined(WITHOUT_BLOG) && defined(WITH_BLOG) -CFLAGS+= -DBLOG -LDFLAGS+= -L/usr/local/lib/mysql -LIBS+= -lmysqlclient -.endif - -.if !defined(WITHOUT_LOG_CRAWLER) && defined(WITH_LOG_CRAWLER) -CFLAGS+= -DLOG_CRAWLER -.endif - -.if !defined(WITHOUT_EMAILDB) && defined(WITH_EMAILDB) -OBJS+= emaildb.o -CFLAGS+= -DUSE_EMAILDB -LIBS+= -lsqlite3 -.endif - -.if !defined(WITHOUT_BBSLUA_USAGE) && defined(WITH_BBSLUA_USAGE) -CFLAGS+= -DBBSLUA_USAGE -.endif - -.if !defined(WITHOUT_BBSLUA) && defined(WITH_BBSLUA) -OBJS+= bbslua.o bbsluaext.o -CFLAGS+= -DUSE_BBSLUA -# MODIFY THESE ENVIRONMENT SETTINGS TO FIT YOUR CONFIGURATION -CFLAGS+= -I/usr/include/lua5.1 -CFLAGS_FreeBSD += -I/usr/local/include/lua51 -LDFLAGS_FreeBSD+= -L/usr/local/lib/lua51 -# modify the lib name below to fit your configuration -# usually you'd try "-llua" instead of "-llua5.1". -LIBS+= -llua5.1 -lm -#LIBS+= -llua -lm -.endif - -.if !defined(WITHOUT_PFTERM) && defined(WITH_PFTERM) -OBJS+= pfterm.o -CFLAGS+= -DUSE_PFTERM -#CFLAGS+= -DDBG_OUTRPT -.else -OBJS+= screen.o -.endif - -####################################################################### -# special library (DIET) configuration -####################################################################### - -.if defined(DIET) -OBJS+= random.o time.o alloc.o -DIETCC= diet -Os -.endif -#CFLAGS+=-g -#CFLAGS+=-std=c99 - -# reduce .bss align overhead -.if !defined(DEBUG) -LDFLAGS+=-Wl,--sort-common -.endif - -.if defined(MERGEBBS) -CFLAGS+= -DMERGEBBS -OBJS+= merge.o -.endif -LIBS+= $(SRCROOT)/src/libbbsutil/libbbsutil.a \ - $(SRCROOT)/src/libbbs/libbbs.a - -####################################################################### -# Make Rules -####################################################################### - -.SUFFIXES: .c .o -.c.o: $(SRCROOT)/include/var.h - $(CCACHE) $(DIETCC) $(CC) $(CFLAGS) -c $*.c - -all: $(PROG) - -$(PROG): $(OBJS) - sh $(SRCROOT)/util/newvers.sh - $(DIETCC) $(CC) $(LDFLAGS) -o $(PROG) $(OBJS) $(LIBS) $(EXT_LIBS) vers.c - -$(SRCROOT)/include/var.h: var.c - perl $(SRCROOT)/util/parsevar.pl < var.c > $(SRCROOT)/include/var.h - -$(SRCROOT)/include/banip.h: $(SRCROOT)/util/banip.pl - perl $(SRCROOT)/util/banip.pl > $@ - -mbbsd.o: mbbsd.c $(SRCROOT)/include/var.h $(SRCROOT)/include/banip.h - $(CCACHE) $(DIETCC) $(CC) $(CFLAGS) -c $< - -initemaildb: emaildb.c - $(CC) -DINIT_MAIN $(CFLAGS) $(LDFLAGS) -o initemaildb emaildb.c $(LIBS) - -ctags: - ctags *.c ../include/*.h ../src/libbbs/*.c ../src/libbbsutil/*.c - -test: $(PROG) - killall -9 testmbbsd || true - cp mbbsd testmbbsd - ./testmbbsd 9000 - rm -f testmbbsd - -install: $(PROG) - install -d $(BBSHOME)/bin/ - install -c -m 755 $(PROG) $(BBSHOME)/bin/ - mv -f $(BBSHOME)/bin/mbbsd $(BBSHOME)/bin/mbbsd.`date '+%m%d%H%M'` - ln -sv $(BBSHOME)/bin/mbbsd.`date '+%m%d%H%M'` $(BBSHOME)/bin/mbbsd - -clean: - rm -f $(OBJS) $(PROG) diff --git a/mbbsd/admin.c b/mbbsd/admin.c deleted file mode 100644 index d0efa3e1..00000000 --- a/mbbsd/admin.c +++ /dev/null @@ -1,1172 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -/* ¶i¯¸¤ô²y«Å¶Ç */ -int -m_loginmsg(void) -{ - char msg[100]; - move(21,0); - clrtobot(); - if(SHM->loginmsg.pid && SHM->loginmsg.pid != currutmp->pid) - { - outs("¥Ø«e¤w¸g¦³¥H¤Uªº ¶i¯¸¤ô²y³]©w½Ð¥ý¨ó½Õ¦n¦A³]©w.."); - getmessage(SHM->loginmsg); - } - getdata(22, 0, - "¶i¯¸¤ô²y:¥»¯¸¬¡°Ê,¤£¤zÂZ¨Ï¥ÎªÌ¬°,³]©wªÌÂ÷¯¸¦Û°Ê¨ú®ø,½T©wn³]?(y/N)", - msg, 3, LCECHO); - - if(msg[0]=='y' && - - getdata_str(23, 0, "³]©w¶i¯¸¤ô²y:", msg, 56, DOECHO, SHM->loginmsg.last_call_in)) - { - SHM->loginmsg.pid=currutmp->pid; /*¯¸ªø¤£¦h ´N¤£ºÞrace condition */ - strcpy(SHM->loginmsg.last_call_in, msg); - strcpy(SHM->loginmsg.userid, cuser.userid); - } - return 0; -} - -/* ¨Ï¥ÎªÌºÞ²z */ -int -m_user(void) -{ - userec_t xuser; - int id; - char genbuf[200]; - - stand_title("¨Ï¥ÎªÌ³]©w"); - usercomplete(msg_uid, genbuf); - if (*genbuf) { - move(2, 0); - if ((id = getuser(genbuf, &xuser))) { - user_display(&xuser, 1); - if( HasUserPerm(PERM_ACCOUNTS) ) - uinfo_query(&xuser, 1, id); - else - pressanykey(); - } else { - outs(err_uid); - clrtoeol(); - pressanykey(); - } - } - return 0; -} - -static int retrieve_backup(userec_t *user) -{ - int uid; - char src[PATHLEN], dst[PATHLEN]; - char ans; - - if ((uid = searchuser(user->userid, user->userid))) { - userec_t orig; - passwd_query(uid, &orig); - strlcpy(user->passwd, orig.passwd, sizeof(orig.passwd)); - setumoney(uid, user->money); - passwd_update(uid, user); - return 0; - } - - ans = getans("¥Ø«eªº PASSWD ÀɨS¦³¦¹ ID¡A·s¼W¶Ü¡H[y/N]"); - - if (ans != 'y') { - vmsg("¥Ø«eªº PASSWDS ÀɨS¦³¦¹ ID¡A½Ð¥ý·s¼W¦¹±b¸¹"); - return -1; - } - - if (setupnewuser((const userec_t *)user) >= 0) { - sethomepath(dst, user->userid); - if (!dashd(dst)) { - snprintf(src, sizeof(src), "tmp/%s", user->userid); - if (!dashd(src) || !Rename(src, dst)) - mkuserdir(user->userid); - } - return 0; - } - return -1; -} - -static int -search_key_user(const char *passwdfile, int mode) -{ - userec_t user; - int ch; - int unum = 0; - FILE *fp1 = fopen(passwdfile, "r"); - char friendfile[128]="", key[22], *keymatch; - int keytype = 0; - char isCurrentPwd = 0; - - isCurrentPwd = (strcmp(passwdfile, FN_PASSWD) == 0) ? 1 : 0; - assert(fp1); - clear(); - if (!mode) - { - getdata(0, 0, "½Ð¿é¤Jid :", key, sizeof(key), DOECHO); - } else { - // improved search - getdata(0, 0, "·j´MþºØÄæ¦ì?" - "([0]¥þ³¡ 1.ID 2.©m¦W 3.¼ÊºÙ 4.¦a§} 5.email 6.IP 7.»{ÃÒ/¹q¸Ü) ", - key, 2, DOECHO); - if (isascii(key[0]) && isdigit(key[0])) - keytype = key[0] - '0'; - if (keytype < 0 || keytype > 7) - keytype = 0; - getdata(0, 0, "½Ð¿é¤JÃöÁä¦r: ", key, sizeof(key), DOECHO); - } - - if(!key[0]) { - fclose(fp1); - return 0; - } - while ((fread(&user, sizeof(user), 1, fp1)) > 0 && unum++ < MAX_USERS) { - - // skip empty records - if (!user.userid[0]) - continue; - - if (!(unum & 0xFF)) { - move(1, 0); - prints("²Ä [%d] µ§¸ê®Æ\n", unum); - refresh(); - } - - keymatch = NULL; - - if (!mode) - { - // only verify id - if (!strcasecmp(user.userid, key)) - keymatch = user.userid; - } else { - // search by keytype - if ((!keytype || keytype == 1) && - strcasestr(user.userid, key)) - keymatch = user.userid; - else if ((!keytype || keytype == 2) && - strcasestr(user.realname, key)) - keymatch = user.realname; - else if ((!keytype || keytype == 3) && - strcasestr(user.nickname, key)) - keymatch = user.nickname; - else if ((!keytype || keytype == 4) && - strcasestr(user.address, key)) - keymatch = user.address; - else if ((!keytype || keytype == 5) && - strcasestr(user.email, key)) - keymatch = user.email; - else if ((!keytype || keytype == 6) && - strcasestr(user.lasthost, key)) - keymatch = user.lasthost; - else if ((!keytype || keytype == 7) && - strcasestr(user.justify, key)) - keymatch = user.justify; - } - - if(keymatch) { - move(1, 0); - prints("²Ä [%d] µ§¸ê®Æ\n", unum); - refresh(); - - user_display(&user, 1); - // user_display does not have linefeed in tail. - - if (isCurrentPwd && HasUserPerm(PERM_ACCOUNTS)) - uinfo_query(&user, 1, unum); - else - outs("\n"); - - outs(ANSI_COLOR(44) " ªÅ¥ÕÁä" \ - ANSI_COLOR(37) ":·j´M¤U¤@Ó " \ - ANSI_COLOR(33)" Q" ANSI_COLOR(37)": Â÷¶}"); - outs(mode ? - " A: add to namelist " ANSI_RESET " " : - " S: ¨ú¥Î³Æ¥÷¸ê®Æ " ANSI_RESET " "); - while (1) { - while ((ch = igetch()) == 0); - if (ch == 'a' || ch=='A' ) - { - if(!friendfile[0]) - { - friend_special(); - setfriendfile(friendfile, FRIEND_SPECIAL); - } - friend_add(user.userid, FRIEND_SPECIAL, keymatch); - break; - } - if (ch == ' ') - break; - if (ch == 'q' || ch == 'Q') { - fclose(fp1); - return 0; - } - if (ch == 's' && !mode) { - if (retrieve_backup(&user) >= 0) { - fclose(fp1); - return 0; - } - } - } - } - } - - fclose(fp1); - return 0; -} - -/* ¥H¥ô·N key ´M§ä¨Ï¥ÎªÌ */ -int -search_user_bypwd(void) -{ - search_key_user(FN_PASSWD, 1); - return 0; -} - -/* ´M§ä³Æ¥÷ªº¨Ï¥ÎªÌ¸ê®Æ */ -int -search_user_bybakpwd(void) -{ - char *choice[] = { - "PASSWDS.NEW1", "PASSWDS.NEW2", "PASSWDS.NEW3", - "PASSWDS.NEW4", "PASSWDS.NEW5", "PASSWDS.NEW6", - "PASSWDS.BAK" - }; - int ch; - - clear(); - move(1, 1); - outs("½Ð¿é¤J§An¥Î¨Ó´M§ä³Æ¥÷ªºÀÉ®× ©Î«ö 'q' Â÷¶}\n"); - outs(" [" ANSI_COLOR(1;31) "1" ANSI_RESET "]¤@¤Ñ«e," - " [" ANSI_COLOR(1;31) "2" ANSI_RESET "]¨â¤Ñ«e," - " [" ANSI_COLOR(1;31) "3" ANSI_RESET "]¤T¤Ñ«e\n"); - outs(" [" ANSI_COLOR(1;31) "4" ANSI_RESET "]¥|¤Ñ«e," - " [" ANSI_COLOR(1;31) "5" ANSI_RESET "]¤¤Ñ«e," - " [" ANSI_COLOR(1;31) "6" ANSI_RESET "]¤»¤Ñ«e\n"); - outs(" [7]³Æ¥÷ªº\n"); - do { - move(5, 1); - outs("¿ï¾Ü => "); - ch = igetch(); - if (ch == 'q' || ch == 'Q') - return 0; - } while (ch < '1' || ch > '7'); - ch -= '1'; - if( access(choice[ch], R_OK) != 0 ) - vmsg("Àɮפ£¦s¦b"); - else - search_key_user(choice[ch], 0); - return 0; -} - -static void -bperm_msg(const boardheader_t * board) -{ - prints("\n³]©w [%s] ¬ÝªO¤§(%s)Åv¡G", board->brdname, - board->brdattr & BRD_POSTMASK ? "µoªí" : "¾\\Ū"); -} - -unsigned int -setperms(unsigned int pbits, const char * const pstring[]) -{ - register int i; - - move(4, 0); - for (i = 0; i < NUMPERMS / 2; i++) { - prints("%c. %-20s %-15s %c. %-20s %s\n", - 'A' + i, pstring[i], - ((pbits >> i) & 1 ? "£¾" : "¢æ"), - i < 10 ? 'Q' + i : '0' + i - 10, - pstring[i + 16], - ((pbits >> (i + 16)) & 1 ? "£¾" : "¢æ")); - } - clrtobot(); - while ( - (i = getkey("½Ð«ö [A-5] ¤Á´«³]©w¡A«ö [Return] µ²§ô¡G"))!='\r') - { - if (isdigit(i)) - i = i - '0' + 26; - else if (isalpha(i)) - i = tolower(i) - 'a'; - else { - bell(); - continue; - } - - pbits ^= (1 << i); - move(i % 16 + 4, i <= 15 ? 24 : 64); - outs((pbits >> i) & 1 ? "£¾" : "¢æ"); - } - return pbits; -} - -#ifdef CHESSCOUNTRY -static void -AddingChessCountryFiles(const char* apath) -{ - char filename[PATHLEN]; - char symbolicname[PATHLEN]; - char adir[PATHLEN]; - FILE* fp; - fileheader_t fh; - - setadir(adir, apath); - - /* creating chess country regalia */ - snprintf(filename, sizeof(filename), "%s/chess_ensign", apath); - close(open(filename, O_CREAT | O_WRONLY, 0644)); - - strlcpy(symbolicname, apath, sizeof(symbolicname)); - stampfile(symbolicname, &fh); - symlink("chess_ensign", symbolicname); - - strcpy(fh.title, "¡º ´Ñ°ê°êÀ² (¤£¯à§R°£¡A¨t²Î»Ýn)"); - strcpy(fh.owner, str_sysop); - append_record(adir, &fh, sizeof(fileheader_t)); - - /* creating member list */ - snprintf(filename, sizeof(filename), "%s/chess_list", apath); - if (!dashf(filename)) { - fp = fopen(filename, "w"); - assert(fp); - fputs("´Ñ°ê°ê¦W\n" - "±b¸¹ ¶¥¯Å ¥[¤J¤é´Á µ¥¯Å©Î³Q½Ö«R¸¸\n" - "¢w¢w¢w¢w¢w¢w ¢w¢w¢w ¢w¢w¢w¢w¢w ¢w¢w¢w¢w¢w¢w¢w\n", - fp); - fclose(fp); - } - - strlcpy(symbolicname, apath, sizeof(symbolicname)); - stampfile(symbolicname, &fh); - symlink("chess_list", symbolicname); - - strcpy(fh.title, "¡º ´Ñ°ê¦¨ûªí (¤£¯à§R°£¡A¨t²Î»Ýn)"); - strcpy(fh.owner, str_sysop); - append_record(adir, &fh, sizeof(fileheader_t)); - - /* creating profession photos' dir */ - snprintf(filename, sizeof(filename), "%s/chess_photo", apath); - mkdir(filename, 0755); - - strlcpy(symbolicname, apath, sizeof(symbolicname)); - stampfile(symbolicname, &fh); - symlink("chess_photo", symbolicname); - - strcpy(fh.title, "¡» ´Ñ°ê·Ó¤ùÀÉ (¤£¯à§R°£¡A¨t²Î»Ýn)"); - strcpy(fh.owner, str_sysop); - append_record(adir, &fh, sizeof(fileheader_t)); -} -#endif /* defined(CHESSCOUNTRY) */ - -/* ¦Û°Ê³]¥ßºëµØ°Ï */ -void -setup_man(const boardheader_t * board, const boardheader_t * oldboard) -{ - char genbuf[200]; - - setapath(genbuf, board->brdname); - mkdir(genbuf, 0755); - -#ifdef CHESSCOUNTRY - if (oldboard == NULL || oldboard->chesscountry != board->chesscountry) - if (board->chesscountry != CHESSCODE_NONE) - AddingChessCountryFiles(genbuf); - // else // doesn't remove files.. -#endif -} - -void delete_symbolic_link(boardheader_t *bh, int bid) -{ - assert(0<=bid-1 && bid-1<MAX_BOARD); - memset(bh, 0, sizeof(boardheader_t)); - substitute_record(fn_board, bh, sizeof(boardheader_t), bid); - reset_board(bid); - sort_bcache(); - log_usies("DelLink", bh->brdname); -} - -int dir_cmp(const void *a, const void *b) -{ - return (atoi( &((fileheader_t *)a)->filename[2] ) - - atoi( &((fileheader_t *)b)->filename[2] )); -} - -void merge_dir(const char *dir1, const char *dir2, int isoutter) -{ - int i, pn, sn; - fileheader_t *fh; - char *p1, *p2, bakdir[128], file1[128], file2[128]; - strcpy(file1,dir1); - strcpy(file2,dir2); - if((p1=strrchr(file1,'/'))) - p1 ++; - else - p1 = file1; - if((p2=strrchr(file2,'/'))) - p2 ++; - else - p2 = file2; - - pn=get_num_records(dir1, sizeof(fileheader_t)); - sn=get_num_records(dir2, sizeof(fileheader_t)); - if(!sn) return; - fh= (fileheader_t *)malloc( (pn+sn)*sizeof(fileheader_t)); - get_records(dir1, fh, sizeof(fileheader_t), 1, pn); - get_records(dir2, fh+pn, sizeof(fileheader_t), 1, sn); - if(isoutter) - { - for(i=0; i<sn; i++) - if(fh[pn+i].owner[0]) - strcat(fh[pn+i].owner, "."); - } - qsort(fh, pn+sn, sizeof(fileheader_t), dir_cmp); - sprintf(bakdir,"%s.bak", dir1); - Rename(dir1, bakdir); - for(i=1; i<=pn+sn; i++ ) - { - if(!fh[i-1].filename[0]) continue; - if(i == pn+sn || strcmp(fh[i-1].filename, fh[i].filename)) - { - fh[i-1].recommend =0; - fh[i-1].filemode |= 1; - append_record(dir1, &fh[i-1], sizeof(fileheader_t)); - strcpy(p1, fh[i-1].filename); - if(!dashf(file1)) - { - strcpy(p2, fh[i-1].filename); - Copy(file2, file1); - } - } - else - fh[i].filemode |= fh[i-1].filemode; - } - - free(fh); -} - -int -m_mod_board(char *bname) -{ - boardheader_t bh, newbh; - int bid; - char genbuf[256], ans[4]; - - bid = getbnum(bname); - if (!bid || !bname[0] || get_record(fn_board, &bh, sizeof(bh), bid) == -1) { - vmsg(err_bid); - return -1; - } - assert(0<=bid-1 && bid-1<MAX_BOARD); - prints("¬ÝªO¦WºÙ¡G%s\n¬ÝªO»¡©ú¡G%s\n¬ÝªObid¡G%d\n¬ÝªOGID¡G%d\n" - "ªO¥D¦W³æ¡G%s", bh.brdname, bh.title, bid, bh.gid, bh.BM); - bperm_msg(&bh); - - /* Ptt ³oÃäÂ_¦æ·|Àɨì¤U± */ - move(9, 0); - snprintf(genbuf, sizeof(genbuf), "(E)³]©w (V)¹Hªk/¸Ñ°£%s%s [Q]¨ú®ø¡H", - HasUserPerm(PERM_SYSOP | - PERM_BOARD) ? " (B)Vote (S)±Ï¦^ (C)¦X¨Ö (G)½ä½L¸Ñ¥d" : "", - HasUserPerm(PERM_SYSSUBOP | PERM_SYSSUPERSUBOP | PERM_BOARD) ? " (D)§R°£" : ""); - getdata(10, 0, genbuf, ans, 3, LCECHO); - - switch (*ans) { - case 'g': - if (HasUserPerm(PERM_SYSOP | PERM_BOARD)) { - char path[PATHLEN]; - setbfile(genbuf, bname, FN_TICKET_LOCK); - setbfile(path, bname, FN_TICKET_END); - rename(genbuf, path); - } - break; - case 's': - if (HasUserPerm(PERM_SYSOP | PERM_BOARD)) { - snprintf(genbuf, sizeof(genbuf), - BBSHOME "/bin/buildir boards/%c/%s &", - bh.brdname[0], bh.brdname); - system(genbuf); - } - break; - case 'c': - if (HasUserPerm(PERM_SYSOP)) { - char frombname[20], fromdir[256]; -#ifdef MERGEBBS - if(getans("¬O§_¶×¤JSOB¬ÝªO? (y/N)")=='y') - { - setbdir(genbuf, bname); - m_sob_brd(bname, fromdir); - if(!fromdir[0]) break; - merge_dir(genbuf, fromdir, 1); - } - else{ -#endif - CompleteBoard(MSG_SELECT_BOARD, frombname); - if (frombname[0] == '\0' || !getbnum(frombname) || - !strcmp(frombname,bname)) - break; - setbdir(genbuf, bname); - setbdir(fromdir, frombname); - merge_dir(genbuf, fromdir, 0); -#ifdef MERGEBBS - } -#endif - touchbtotal(bid); - } - break; - case 'b': - if (HasUserPerm(PERM_SYSOP | PERM_BOARD)) { - char bvotebuf[10]; - - memcpy(&newbh, &bh, sizeof(bh)); - snprintf(bvotebuf, sizeof(bvotebuf), "%d", newbh.bvote); - move(20, 0); - prints("¬ÝªO %s ì¨Óªº BVote¡G%d", bh.brdname, bh.bvote); - getdata_str(21, 0, "·sªº Bvote¡G", genbuf, 5, LCECHO, bvotebuf); - newbh.bvote = atoi(genbuf); - assert(0<=bid-1 && bid-1<MAX_BOARD); - substitute_record(fn_board, &newbh, sizeof(newbh), bid); - reset_board(bid); - log_usies("SetBoardBvote", newbh.brdname); - break; - } else - break; - case 'v': - memcpy(&newbh, &bh, sizeof(bh)); - outs("¬ÝªO¥Ø«e¬°"); - outs((bh.brdattr & BRD_BAD) ? "¹Hªk" : "¥¿±`"); - getdata(21, 0, "½T©w§ó§ï¡H", genbuf, 5, LCECHO); - if (genbuf[0] == 'y') { - if (newbh.brdattr & BRD_BAD) - newbh.brdattr = newbh.brdattr & (!BRD_BAD); - else - newbh.brdattr = newbh.brdattr | BRD_BAD; - assert(0<=bid-1 && bid-1<MAX_BOARD); - substitute_record(fn_board, &newbh, sizeof(newbh), bid); - reset_board(bid); - log_usies("ViolateLawSet", newbh.brdname); - } - break; - case 'd': - if (!(HasUserPerm(PERM_SYSOP | PERM_BOARD) || - (HasUserPerm(PERM_SYSSUPERSUBOP) && GROUPOP()))) - break; - getdata_str(9, 0, msg_sure_ny, genbuf, 3, LCECHO, "N"); - if (genbuf[0] != 'y' || !bname[0]) - outs(MSG_DEL_CANCEL); - else if (bh.brdattr & BRD_SYMBOLIC) { - delete_symbolic_link(&bh, bid); - } - else { - strlcpy(bname, bh.brdname, sizeof(bh.brdname)); - snprintf(genbuf, sizeof(genbuf), - "/bin/tar zcvf tmp/board_%s.tgz boards/%c/%s man/boards/%c/%s >/dev/null 2>&1;" - "/bin/rm -fr boards/%c/%s man/boards/%c/%s", - bname, bname[0], bname, bname[0], - bname, bname[0], bname, bname[0], bname); - system(genbuf); - memset(&bh, 0, sizeof(bh)); - snprintf(bh.title, sizeof(bh.title), - " %s ¬ÝªO %s §R°£", bname, cuser.userid); - post_msg(GLOBAL_SECURITY, bh.title, "½Ðª`·N§R°£ªº¦Xªk©Ê", "[¨t²Î¦w¥þ§½]"); - assert(0<=bid-1 && bid-1<MAX_BOARD); - substitute_record(fn_board, &bh, sizeof(bh), bid); - reset_board(bid); - sort_bcache(); - log_usies("DelBoard", bh.title); - outs("§RªO§¹²¦"); - } - break; - case 'e': - if( bh.brdattr & BRD_SYMBOLIC ){ - vmsg("¸T¤î§ó°Ê³sµ²¬ÝªO¡A½Ðª½±µ×¥¿ì¬ÝªO"); - break; - } - move(8, 0); - outs("ª½±µ«ö [Return] ¤£×§ï¸Ó¶µ³]©w"); - memcpy(&newbh, &bh, sizeof(bh)); - - while (getdata(9, 0, "·s¬ÝªO¦WºÙ¡G", genbuf, IDLEN + 1, DOECHO)) { - if (getbnum(genbuf)) { - move(3, 0); - outs("¿ù»~! ªO¦W¹p¦P"); - } else if ( !invalid_brdname(genbuf) ){ - strlcpy(newbh.brdname, genbuf, sizeof(newbh.brdname)); - break; - } - } - - do { - getdata_str(12, 0, "¬ÝªOÃþ§O¡G", genbuf, 5, DOECHO, bh.title); - if (strlen(genbuf) == 4) - break; - } while (1); - - strcpy(newbh.title, genbuf); - - newbh.title[4] = ' '; - - getdata_str(14, 0, "¬ÝªO¥DÃD¡G", genbuf, BTLEN + 1, DOECHO, - bh.title + 7); - if (genbuf[0]) - strlcpy(newbh.title + 7, genbuf, sizeof(newbh.title) - 7); - if (getdata_str(15, 0, "·sªO¥D¦W³æ¡G", genbuf, IDLEN * 3 + 3, DOECHO, - bh.BM)) { - trim(genbuf); - strlcpy(newbh.BM, genbuf, sizeof(newbh.BM)); - } -#ifdef CHESSCOUNTRY - if (HasUserPerm(PERM_SYSOP)) { - snprintf(genbuf, sizeof(genbuf), "%d", bh.chesscountry); - if (getdata_str(16, 0, "³]©w´Ñ°ê (0)µL (1)¤¤l´Ñ (2)¶H´Ñ (3)³ò´Ñ", ans, - sizeof(ans), LCECHO, genbuf)){ - newbh.chesscountry = atoi(ans); - if (newbh.chesscountry > CHESSCODE_MAX || - newbh.chesscountry < CHESSCODE_NONE) - newbh.chesscountry = bh.chesscountry; - } - } -#endif /* defined(CHESSCOUNTRY) */ - if (HasUserPerm(PERM_SYSOP|PERM_BOARD)) { - move(1, 0); - clrtobot(); - newbh.brdattr = setperms(newbh.brdattr, str_permboard); - move(1, 0); - clrtobot(); - } - { - const char* brd_symbol; - if (newbh.brdattr & BRD_GROUPBOARD) - brd_symbol = "£U"; - else if (newbh.brdattr & BRD_NOTRAN) - brd_symbol = "¡·"; - else - brd_symbol = "¡´"; - - newbh.title[5] = brd_symbol[0]; - newbh.title[6] = brd_symbol[1]; - } - - if (HasUserPerm(PERM_SYSOP|PERM_BOARD) && !(newbh.brdattr & BRD_HIDE)) { - getdata_str(14, 0, "³]©wŪ¼gÅv(Y/N)¡H", ans, sizeof(ans), LCECHO, "N"); - if (*ans == 'y') { - getdata_str(15, 0, "¨î [R]¾\\Ū (P)µoªí¡H", ans, sizeof(ans), LCECHO, - "R"); - if (*ans == 'p') - newbh.brdattr |= BRD_POSTMASK; - else - newbh.brdattr &= ~BRD_POSTMASK; - - move(1, 0); - clrtobot(); - bperm_msg(&newbh); - newbh.level = setperms(newbh.level, str_permid); - clear(); - } - } - - getdata(b_lines - 1, 0, "½Ð±z½T©w(Y/N)¡H[Y]", genbuf, 4, LCECHO); - - if ((*genbuf != 'n') && memcmp(&newbh, &bh, sizeof(bh))) { - char buf[64]; - - if (strcmp(bh.brdname, newbh.brdname)) { - char src[60], tar[60]; - - setbpath(src, bh.brdname); - setbpath(tar, newbh.brdname); - Rename(src, tar); - - setapath(src, bh.brdname); - setapath(tar, newbh.brdname); - Rename(src, tar); - } - setup_man(&newbh, &bh); - assert(0<=bid-1 && bid-1<MAX_BOARD); - substitute_record(fn_board, &newbh, sizeof(newbh), bid); - reset_board(bid); - sort_bcache(); - log_usies("SetBoard", newbh.brdname); - - snprintf(buf, sizeof(buf), "[¬ÝªOÅܧó] %s (by %s)", bh.brdname, cuser.userid); - snprintf(genbuf, sizeof(genbuf), - "ªO¦W: %s => %s\n" - "ªO¥D: %s => %s\n", - bh.brdname, newbh.brdname, bh.BM, newbh.BM); - post_msg(GLOBAL_SECURITY, buf, genbuf, "[¨t²Î¦w¥þ§½]"); - } - } - return 0; -} - -/* ³]©w¬ÝªO */ -int -m_board(void) -{ - char bname[32]; - - stand_title("¬ÝªO³]©w"); - CompleteBoardAndGroup(msg_bid, bname); - if (!*bname) - return 0; - m_mod_board(bname); - return 0; -} - -/* ³]©w¨t²ÎÀÉ®× */ -int -x_file(void) -{ - int aborted, num; - char ans[4], *fpath, buf[256]; - - move(b_lines - 7, 0); - /* Ptt */ - outs("³]©w (1)¨¥÷½T»{«H (4)postª`·N¨Æ¶µ (5)¿ù»~µn¤J°T®§ (6)µù¥U½d¨Ò (7)³q¹L½T»{³qª¾\n"); - outs(" (8)email post³qª¾ (9)¨t²Î¥\\¯àºëÆF (A)¯ù¼Ó (B)¯¸ªø¦W³æ (C)email³q¹L½T»{\n"); - outs(" (D)·s¨Ï¥ÎªÌ»Ýª¾ (E)¨¥÷½T»{¤èªk (F)Åwªïµe± (G)¶i¯¸µe± " -#ifdef MULTI_WELCOME_LOGIN - "(X)§R°£¶i¯¸µe±" -#endif - "\n"); - outs(" (H)¬ÝªO´Á (I)¬G¶m (J)¥X¯¸µe± (K)¥Í¤é¥d (L)¸`¤é (M)¥~Äy¨Ï¥ÎªÌ»{ÃÒ³qª¾\n"); - outs(" (N)¥~Äy¨Ï¥ÎªÌ¹L´Áĵ§i³qª¾ (O)¬ÝªO¦Cªí help (P)¤å³¹¦Cªí help\n"); -#ifdef PLAY_ANGEL - outs(" (R)¤p¤Ñ¨Ï»{ÃÒ³qª¾ (S)¤p¤Ñ¨Ï¥\\¯à»¡©ú\n"); -#endif - getdata(b_lines - 1, 0, "[Q]¨ú®ø[1-9 A-P]¡H", ans, sizeof(ans), LCECHO); - - switch (ans[0]) { - case '1': - fpath = "etc/confirm"; - break; - case '4': - fpath = "etc/post.note"; - break; - case '5': - fpath = "etc/goodbye"; - break; - case '6': - fpath = "etc/register"; - break; - case '7': - fpath = "etc/registered"; - break; - case '8': - fpath = "etc/emailpost"; - break; - case '9': - fpath = "etc/hint"; - break; - case 'b': - fpath = "etc/sysop"; - break; - case 'c': - fpath = "etc/bademail"; - break; - case 'd': - fpath = "etc/newuser"; - break; - case 'e': - fpath = "etc/justify"; - break; - case 'f': - fpath = "etc/Welcome"; - break; - case 'g': -#ifdef MULTI_WELCOME_LOGIN - getdata(b_lines - 1, 0, "²Ä´XÓ¶i¯¸µe±[0-4]", ans, sizeof(ans), LCECHO); - if (ans[0] == '1') { - fpath = "etc/Welcome_login.1"; - } else if (ans[0] == '2') { - fpath = "etc/Welcome_login.2"; - } else if (ans[0] == '3') { - fpath = "etc/Welcome_login.3"; - } else if (ans[0] == '4') { - fpath = "etc/Welcome_login.4"; - } else { - fpath = "etc/Welcome_login.0"; - } -#else - fpath = "etc/Welcome_login"; -#endif - break; - -#ifdef MULTI_WELCOME_LOGIN - case 'x': - getdata(b_lines - 1, 0, "²Ä´XÓ¶i¯¸µe±[1-4]", ans, sizeof(ans), LCECHO); - if (ans[0] == '1') { - unlink("etc/Welcome_login.1"); - vmsg("ok"); - } else if (ans[0] == '2') { - unlink("etc/Welcome_login.2"); - vmsg("ok"); - } else if (ans[0] == '3') { - unlink("etc/Welcome_login.3"); - vmsg("ok"); - } else if (ans[0] == '4') { - unlink("etc/Welcome_login.4"); - vmsg("ok"); - } else { - vmsg("©Ò«ü©wªº¶i¯¸µe±µLªk§R°£"); - } - return FULLUPDATE; - -#endif - - case 'h': - fpath = "etc/expire.conf"; - break; - case 'i': - fpath = "etc/domain_name_query.cidr"; - break; - case 'j': - fpath = "etc/Logout"; - break; - case 'k': - mouts(b_lines - 3, 0, "1.¼¯½~ 2.¤ô²~ 3.Âù³½ 4.¨d¦Ï 5.ª÷¤û 6.Âù¤l"); - mouts(b_lines - 2, 0, "7.¥¨ÃÉ 8.·à¤l 9.³B¤k 10.¤Ñ¯¯ 11.¤ÑÃÈ 12.®g¤â"); - getdata(b_lines - 1, 0, "½Ð¿ï¾Ü [1-12]", ans, sizeof(ans), LCECHO); - num = atoi(ans); - if (num <= 0 || num > 12) - return FULLUPDATE; - snprintf(buf, sizeof(buf), "etc/Welcome_birth.%d", num); - fpath = buf; - break; - case 'l': - fpath = "etc/feast"; - break; - case 'm': - fpath = "etc/foreign_welcome"; - break; - case 'n': - fpath = "etc/foreign_expired_warn"; - break; - case 'o': - fpath = "etc/boardlist.help"; - break; - case 'p': - fpath = "etc/board.help"; - break; - -#ifdef PLAY_ANGEL - case 'r': - fpath = "etc/angel_notify"; - break; - - case 's': - fpath = "etc/angel_usage"; - break; -#endif - - default: - return FULLUPDATE; - } - aborted = vedit(fpath, NA, NULL); - vmsgf("\n\n¨t²ÎÀÉ®×[%s]: %s", fpath, - (aborted == -1) ? "¥¼§ïÅÜ" : "§ó·s§¹²¦"); - return FULLUPDATE; -} - -static int add_board_record(const boardheader_t *board) -{ - int bid; - if ((bid = getbnum("")) > 0) { - assert(0<=bid-1 && bid-1<MAX_BOARD); - substitute_record(fn_board, board, sizeof(boardheader_t), bid); - reset_board(bid); - sort_bcache(); - } else if (append_record(fn_board, (fileheader_t *)board, sizeof(boardheader_t)) == -1) { - return -1; - } else { - addbrd_touchcache(); - } - return 0; -} - -/** - * open a new board - * @param whatclass In which sub class - * @param recover Forcely open a new board, often used for recovery. - * @return -1 if failed - */ -int -m_newbrd(int whatclass, int recover) -{ - boardheader_t newboard; - char ans[4]; - char genbuf[200]; - - stand_title("«Ø¥ß·sªO"); - memset(&newboard, 0, sizeof(newboard)); - - newboard.gid = whatclass; - if (newboard.gid == 0) { - vmsg("½Ð¥ý¿ï¾Ü¤@ÓÃþ§O¦A¶}ªO!"); - return -1; - } - do { - if (!getdata(3, 0, msg_bid, newboard.brdname, - sizeof(newboard.brdname), DOECHO)) - return -1; - } while (invalid_brdname(newboard.brdname)); - - do { - getdata(6, 0, "¬ÝªOÃþ§O¡G", genbuf, 5, DOECHO); - if (strlen(genbuf) == 4) - break; - } while (1); - - strcpy(newboard.title, genbuf); - - newboard.title[4] = ' '; - - getdata(8, 0, "¬ÝªO¥DÃD¡G", genbuf, BTLEN + 1, DOECHO); - if (genbuf[0]) - strlcpy(newboard.title + 7, genbuf, sizeof(newboard.title) - 7); - setbpath(genbuf, newboard.brdname); - - if (!recover && - (getbnum(newboard.brdname) > 0 || mkdir(genbuf, 0755) == -1)) { - vmsg("¦¹¬ÝªO¤w¸g¦s¦b! ½Ð¨ú¤£¦P^¤åªO¦W"); - return -1; - } - newboard.brdattr = BRD_NOTRAN; -#ifdef DEFAULT_AUTOCPLOG - newboard.brdattr |= BRD_CPLOG; -#endif - - if (HasUserPerm(PERM_SYSOP)) { - move(1, 0); - clrtobot(); - newboard.brdattr = setperms(newboard.brdattr, str_permboard); - move(1, 0); - clrtobot(); - } - getdata(9, 0, "¬O¬ÝªO? (N:¥Ø¿ý) (Y/n)¡G", genbuf, 3, LCECHO); - if (genbuf[0] == 'n') - { - newboard.brdattr |= BRD_GROUPBOARD; - newboard.brdattr &= ~BRD_CPLOG; - } - - { - const char* brd_symbol; - if (newboard.brdattr & BRD_GROUPBOARD) - brd_symbol = "£U"; - else if (newboard.brdattr & BRD_NOTRAN) - brd_symbol = "¡·"; - else - brd_symbol = "¡´"; - - newboard.title[5] = brd_symbol[0]; - newboard.title[6] = brd_symbol[1]; - } - - newboard.level = 0; - getdata(11, 0, "ªO¥D¦W³æ¡G", newboard.BM, sizeof(newboard.BM), DOECHO); -#ifdef CHESSCOUNTRY - if (getdata_str(12, 0, "³]©w´Ñ°ê (0)µL (1)¤¤l´Ñ (2)¶H´Ñ (3)³ò´Ñ", ans, - sizeof(ans), LCECHO, "0")){ - newboard.chesscountry = atoi(ans); - if (newboard.chesscountry > CHESSCODE_MAX || - newboard.chesscountry < CHESSCODE_NONE) - newboard.chesscountry = CHESSCODE_NONE; - } -#endif /* defined(CHESSCOUNTRY) */ - - if (HasUserPerm(PERM_SYSOP) && !(newboard.brdattr & BRD_HIDE)) { - getdata_str(14, 0, "³]©wŪ¼gÅv(Y/N)¡H", ans, sizeof(ans), LCECHO, "N"); - if (*ans == 'y') { - getdata_str(15, 0, "¨î [R]¾\\Ū (P)µoªí¡H", ans, sizeof(ans), LCECHO, "R"); - if (*ans == 'p') - newboard.brdattr |= BRD_POSTMASK; - else - newboard.brdattr &= (~BRD_POSTMASK); - - move(1, 0); - clrtobot(); - bperm_msg(&newboard); - newboard.level = setperms(newboard.level, str_permid); - clear(); - } - } - - add_board_record(&newboard); - getbcache(whatclass)->childcount = 0; - pressanykey(); - setup_man(&newboard, NULL); - outs("\n·sªO¦¨¥ß"); - post_newboard(newboard.title, newboard.brdname, newboard.BM); - log_usies("NewBoard", newboard.title); - pressanykey(); - return 0; -} - -int make_symbolic_link(const char *bname, int gid) -{ - boardheader_t newboard; - int bid; - - bid = getbnum(bname); - if(bid==0) return -1; - assert(0<=bid-1 && bid-1<MAX_BOARD); - memset(&newboard, 0, sizeof(newboard)); - - /* - * known issue: - * These two stuff will be used for sorting. But duplicated brdnames - * may cause wrong binary-search result. So I replace the last - * letters of brdname to '~'(ascii code 126) in order to correct the - * resuilt, thought I think it's a dirty solution. - * - * Duplicate entry with same brdname may cause wrong result, if - * searching by key brdname. But people don't need to know a board - * is symbolic, so just let SYSOP know it. You may want to read - * board.c:load_boards(). - */ - - strlcpy(newboard.brdname, bname, sizeof(newboard.brdname)); - newboard.brdname[strlen(bname) - 1] = '~'; - strlcpy(newboard.title, bcache[bid - 1].title, sizeof(newboard.title)); - strcpy(newboard.title + 5, "¢I¬ÝªO³sµ²"); - - newboard.gid = gid; - BRD_LINK_TARGET(&newboard) = bid; - newboard.brdattr = BRD_NOTRAN | BRD_SYMBOLIC; - - if (add_board_record(&newboard) < 0) - return -1; - return bid; -} - -int make_symbolic_link_interactively(int gid) -{ - char buf[32]; - - CompleteBoard(msg_bid, buf); - if (!buf[0]) - return -1; - - stand_title("«Ø¥ß¬ÝªO³sµ²"); - - if (make_symbolic_link(buf, gid) < 0) { - vmsg("¬ÝªO³sµ²«Ø¥ß¥¢±Ñ"); - return -1; - } - log_usies("NewSymbolic", buf); - return 0; -} - -static void -give_id_money(const char *user_id, int money, const char *mail_title) -{ - char tt[TTLEN + 1] = {0}; - - if (deumoney(searchuser(user_id, NULL), money) < 0) { // TODO if searchuser() return 0 - move(12, 0); - clrtoeol(); - prints("id:%s money:%d ¤£¹ï§a!!", user_id, money); - pressanykey(); - } else { - snprintf(tt, sizeof(tt), "%s : %d " MONEYNAME " ¹ô", mail_title, money); - mail_id(user_id, tt, "etc/givemoney.why", "[PTT »È¦æ]"); - } -} - -int -give_money(void) -{ - FILE *fp, *fp2; - char *ptr, *id, *mn; - char buf[200] = "", reason[100], tt[TTLEN + 1] = ""; - int to_all = 0, money = 0; - int total_money=0, count=0; - - getdata(0, 0, "«ü©w¨Ï¥ÎªÌ(S) ¥þ¯¸¨Ï¥ÎªÌ(A) ¨ú®ø(Q)¡H[S]", buf, 3, LCECHO); - if (buf[0] == 'q') - return 1; - else if (buf[0] == 'a') { - to_all = 1; - getdata(1, 0, "µo¦h¤Ö¿ú©O?", buf, 20, DOECHO); - money = atoi(buf); - if (money <= 0) { - move(2, 0); - vmsg("¿é¤J¿ù»~!!"); - return 1; - } - } else { - if (vedit("etc/givemoney.txt", NA, NULL) < 0) - return 1; - } - - clear(); - - unlink("etc/givemoney.log"); - if (!(fp2 = fopen("etc/givemoney.log", "w"))) - return 1; - - getdata(0, 0, "°Ê¥Î°ê®w!½Ð¿é¤J¥¿·í²z¥Ñ(¦p¬¡°Ê¦WºÙ):", reason, 40, LCECHO); - fprintf(fp2,"\n¨Ï¥Î²z¥Ñ: %s\n", reason); - - getdata(1, 0, "nµo¿ú¤F¶Ü(Y/N)[N]", buf, 3, LCECHO); - if (buf[0] != 'y') - { - fclose(fp2); - return 1; - } - - getdata(1, 0, "¬õ¥]³U¼ÐÃD ¡G", tt, TTLEN, DOECHO); - fprintf(fp2,"\n¬õ¥]³U¼ÐÃD: %s\n", tt); - move(2, 0); - - vmsg("½s¬õ¥]³U¤º®e"); - if (vedit("etc/givemoney.why", NA, NULL) < 0) { - fclose(fp2); - return 1; - } - - stand_title("µo¿ú¤¤..."); - if (to_all) { - int i, unum; - for (unum = SHM->number, i = 0; i < unum; i++) { - if (bad_user_id(SHM->userid[i])) - continue; - id = SHM->userid[i]; - give_id_money(id, money, tt); - fprintf(fp2,"µ¹ %s : %d\n", id, money); - count++; - } - sprintf(buf, "(%d¤H:%d"MONEYNAME"¹ô)", count, count*money); - strcat(reason, buf); - } else { - if (!(fp = fopen("etc/givemoney.txt", "r+"))) { - fclose(fp2); - return 1; - } - while (fgets(buf, sizeof(buf), fp)) { - clear(); - if (!(ptr = strchr(buf, ':'))) - continue; - *ptr = '\0'; - id = buf; - mn = ptr + 1; - money = atoi(mn); - give_id_money(id, money, tt); - fprintf(fp2,"µ¹ %s : %d\n", id, money); - total_money += money; - count++; - } - fclose(fp); - sprintf(buf, "(%d¤H:%d"MONEYNAME"¹ô)", count, total_money); - strcat(reason, buf); - - } - - fclose(fp2); - - sprintf(buf, "%s ¬õ¥]¾÷: %s", cuser.userid, reason); - post_file(GLOBAL_SECURITY, buf, "etc/givemoney.log", "[¬õ¥]¾÷³ø§i]"); - pressanykey(); - return FULLUPDATE; -} diff --git a/mbbsd/aids.c b/mbbsd/aids.c deleted file mode 100644 index 56d19378..00000000 --- a/mbbsd/aids.c +++ /dev/null @@ -1,290 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#error "Not complete yet" - -aidu_t fn2aidu(char *fn) -{ - aidu_t aidu = 0; - aidu_t type = 0; - aidu_t v1 = 0; - aidu_t v2 = 0; - char *sp = fn; - - if(fn == NULL) - return 0; - - switch(*(sp ++)) - { - case 'M': - type = 0; - break; - case 'G': - type = 1; - break; - default: - return 0; - break; - } - - if(*(sp ++) != '.') - return 0; - v1 = strtoul(sp, &sp, 10); - if(sp == NULL) - return 0; - if(*sp != '.' || *(sp + 1) != 'A') - return 0; - sp += 2; - if(*(sp ++) == '.') - { - v2 = strtoul(sp, &sp, 16); - if(sp == NULL) - return 0; - } - aidu = ((type & 0xf) << 44) | ((v1 & 0xffffffff) << 12) | (v2 & 0xfff); - - return aidu; -} - -/* IMPORTANT: - * size of buf must be at least 8+1 bytes - */ -char *aidu2aidc(char *buf, aidu_t aidu) -{ - const char aidu2aidc_table[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_"; - const int aidu2aidc_tablesize = sizeof(aidu2aidc_table) - 1; - char *sp = buf + 8; - aidu_t v; - - *(sp --) = '\0'; - while(sp >= buf) - { - /* FIXME: ¯à«OÃÒ aidu2aidc_tablesize ¬O 2 ªº¾¦¸ªº¸Ü¡A - ³o¸Ì¥i¥H§ï¥Î bitwise operation °µ */ - v = aidu % aidu2aidc_tablesize; - aidu = aidu / aidu2aidc_tablesize; - *(sp --) = aidu2aidc_table[v]; - } - return buf; -} - -/* IMPORTANT: - * size of fn must be at least FNLEN bytes - */ -char *aidu2fn(char *fn, aidu_t aidu) -{ - aidu_t type = ((aidu >> 44) & 0xf); - aidu_t v1 = ((aidu >> 12) & 0xffffffff); - aidu_t v2 = (aidu & 0xfff); - - if(fn == NULL) - return NULL; - snprintf(fn, FNLEN, "%c.%d.A.%03X", ((type == 0) ? 'M' : 'G'), (unsigned int)v1, (unsigned int)v2); - return fn; -} - -aidu_t aidc2aidu(char *aidc) -{ - char *sp = aidc; - aidu_t aidu = 0; - - if(aidc == NULL) - return 0; - - while(*sp != '\0' && /* ignore trailing spaces */ *sp != ' ') - { - aidu_t v = 0; - /* FIXME: ¬dªíªk·|¤£·|¤ñ¸û§Ö¡H */ - if(*sp >= '0' && *sp <= '9') - v = *sp - '0'; - else if(*sp >= 'A' && *sp <= 'Z') - v = *sp - 'A' + 10; - else if(*sp >= 'a' && *sp <= 'z') - v = *sp - 'a' + 36; - else if(*sp == '-') - v = 62; - else if(*sp == '_') - v = 63; - else if(*sp == '@') - break; - else - return 0; - aidu <<= 6; - aidu |= (v & 0x3f); - sp ++; - } - - return aidu; -} - -int search_aidu_in_bfile(char *bfile, aidu_t aidu) -{ - char fn[FNLEN]; - int fd; - fileheader_t fhs[64]; - int len, i; - int pos = 0; - int found = 0; - int lastpos = 0; - - if(aidu2fn(fn, aidu) == NULL) - return -1; - if((fd = open(bfile, O_RDONLY, 0)) < 0) - return -1; - - while(!found && (len = read(fd, fhs, sizeof(fhs))) > 0) - { - len /= sizeof(fileheader_t); - for(i = 0; i < len; i ++) - { - int l; - if(strcmp(fhs[i].filename, fn) == 0 || - ((aidu & 0xfff) == 0 && (l = strlen(fhs[i].filename)) > 6 && - strncmp(fhs[i].filename, fn, l) == 0)) - { - if(fhs[i].filemode & FILE_BOTTOM) - { - lastpos = pos; - } - else - { - found = 1; - break; - } - } - pos ++; - } - } - close(fd); - - return (found ? pos : (lastpos ? lastpos : -1)); -} - -SearchAIDResult_t search_aidu_in_board(char *bname, aidu_t aidu) -{ - SearchAIDResult_t r = {AIDR_BOARD, -1}: - int n = -1; - char dirfile[PATHLEN]; - - { - char bf[FNLEN]; - - snprintf(bf, FNLEN, "%s.bottom", FN_DIR); - setbfile(dirfile, bname, bf); - if((n = search_aidu_in_bfile(dirfile, aidu)) >= 0) - { - r.where = AIDR_BOTTOM; - r.n = n; - } - } - if(r.n < 0) - { - setbfile(dirfile, bname, FN_DIR); - if((n = search_aidu_in_bfile(dirfile, aidu)) >= 0) - { - r.where = AIDR_BOARD; - r.n = n; - } - } - if(r.n < 0) - { - setbfile(dirfile, bname, fn_mandex); - if((n = search_aidu_in_bfile(dirfile, aidu)) >= 0) - { - r.where = AIDR_DIGEST; - r.n = n; - } - } - return r; -} - -SearchAIDResult_t do_search_aid(void) -{ - SearchAIDResult_t r = {AIDR_BOARD, -1}; - char aidc[100]; - char bname[IDLEN + 1] = ""; - aidu_t aidu = 0; - char *sp; - char *sp2; - char *emsg = NULL; - - if(!getdata(b_lines, 0, "·j´M" AID_DISPLAYNAME ": #", aidc, 15 + IDLEN, LCECHO)) - { - move(b_lines, 0); - clrtorol(); - r.n = -1; - return r; - } - - if(currstat == RMAIL) - { - move(21, 0); - clrtobot(); - move(22, 0); - prints("¦¹ª¬ºA¤UµLªk·j´M" AID_DISPLAYNAME); - pressanykey(); - r.n = -1; - return r; - } - - sp = aidc; - while(*sp == ' ') - sp ++; - while(*sp == '#') - sp ++; - aidu = aidc2aidu(sp); - if((sp2 = strchr(sp, '@')) != NULL) - { - // assert(sizeof(bname) > IDLEN); - strlcpy(bname, sp2 + 1, IDLEN+1); - *sp2 = '\0'; - } - else - bname[0] = '\0'; - - if(aidu > 0) - { - if(bname[0] != '\0') - { - if(!HasBoardPerm_bn(bname)) - return FULLUPDATE; - r = search_aidu_in_board(bname, aidu); - if(r.n >= 0) - { - if(enter_board(bname) < 0) - { - r.n = -1; - emsg = "¿ù»~¡GµLªk¶i¤J«ü©wªº¬ÝªO %s"; - } - } - } - else - { - r = search_aidu_in_board(currboard, aidu); - } - } - - if(r.n < 0) - { - if(aidu == 0) - emsg = "¤£¦Xªkªº" AID_DISPLAYNAME "¡A½Ð½T©w¿é¤J¬O¥¿½Tªº"; - else if(emsg == NULL) - { - if(bname[0] != '\0') - emsg = "¬ÝªO %s ¤º§ä¤£¨ì³oÓ" AID_DISPLAYNAME "¡A¥i¯à¬O¤å³¹¤w¸g®ø¥¢¡A©Î¬O§ä¿ù¬ÝªO¤F"; - else - emsg = "§ä¤£¨ì³oÓ" AID_DISPLAYNAME "¡A¥i¯à¬O¤å³¹¤w¸g®ø¥¢¡A©Î¬O§ä¿ù¬ÝªO¤F"; - } - move(21, 0); - clrtoeol(); - move(22, 0); - prints(emsg, bname); - pressanykey(); - r.n = -1; - return r; - } - else - { - return r; - } -} diff --git a/mbbsd/alloc.c b/mbbsd/alloc.c deleted file mode 100644 index de676ce4..00000000 --- a/mbbsd/alloc.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * malloc/free by O.Dreesen - * - * first TRY: - * lists w/magics - * and now the second TRY - * let the kernel map all the stuff (if there is something to do) - */ - -#include <unistd.h> -#include <sys/mman.h> -#include <errno.h> - -#include <sys/cdefs.h> -#include <sys/types.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> - -#include <sys/shm.h> /* for PAGE_SIZE */ - - -/* -- HELPER CODE --------------------------------------------------------- */ - -#ifndef MAP_FAILED -#define MAP_FAILED ((void*)-1) -#endif - -#ifndef NULL -#define NULL ((void*)0) -#endif - -typedef struct { - void* next; - size_t size; -} __alloc_t; - -#define BLOCK_START(b) (((void*)(b))-sizeof(__alloc_t)) -#define BLOCK_RET(b) (((void*)(b))+sizeof(__alloc_t)) - -#define MEM_BLOCK_SIZE PAGE_SIZE -#define PAGE_ALIGN(s) (((s)+MEM_BLOCK_SIZE-1)&(unsigned long)(~(MEM_BLOCK_SIZE-1))) - -/* a simple mmap :) */ -#if defined(__i386__) -#define REGPARM(x) __attribute__((regparm(x))) -#else -#define REGPARM(x) -#endif - -static void REGPARM(1) *do_mmap(size_t size) { - return mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (size_t)0); -} - -/* -- SMALL MEM ----------------------------------------------------------- */ - -static __alloc_t* __small_mem[8]; - -static int smallalloc[8]; -static int smallalloc_max[8]; - -#define __SMALL_NR(i) (MEM_BLOCK_SIZE/(i)) - -#define __MIN_SMALL_SIZE __SMALL_NR(256) /* 16 / 32 */ -#define __MAX_SMALL_SIZE __SMALL_NR(2) /* 2048 / 4096 */ - -#define GET_SIZE(s) (__MIN_SMALL_SIZE<<get_index((s))) - -#define FIRST_SMALL(p) (((unsigned long)(p))&(~(MEM_BLOCK_SIZE-1))) - -static inline int __ind_shift() { return (MEM_BLOCK_SIZE==4096)?4:5; } - -static size_t REGPARM(1) get_index(size_t _size) { - register size_t idx=0; -// if (_size) { /* we already check this in the callers */ - register size_t size=((_size-1)&(MEM_BLOCK_SIZE-1))>>__ind_shift(); - while(size) { size>>=1; ++idx; } -// } - return idx; -} - -/* small mem */ -static void __small_free(void*_ptr,size_t _size) REGPARM(2); - -static void REGPARM(2) __small_free(void*_ptr,size_t _size) { - __alloc_t* ptr=BLOCK_START(_ptr); - size_t size=_size; - size_t idx=get_index(size); - - memset(ptr,0,size); /* allways zero out small mem */ - - ptr->next=__small_mem[idx]; - __small_mem[idx]=ptr; - - smallalloc[idx]--; - - if (MEM_BLOCK_SIZE == PAGE_SIZE && - smallalloc[idx] == 0 && - smallalloc_max[idx] < __SMALL_NR(size)) { - __alloc_t* p = __small_mem[idx]; - __alloc_t* ph = p - (size_t)p%PAGE_SIZE; - munmap(ph, MEM_BLOCK_SIZE); - __small_mem[idx] = 0; - } -} - -static void* REGPARM(1) __small_malloc(size_t _size) { - __alloc_t *ptr; - size_t size=_size; - size_t idx; - - idx=get_index(size); - ptr=__small_mem[idx]; - - if (ptr==0) { /* no free blocks ? */ - register int i,nr; - ptr=do_mmap(MEM_BLOCK_SIZE); - if (ptr==MAP_FAILED) return MAP_FAILED; - - __small_mem[idx]=ptr; - - nr=__SMALL_NR(size)-1; - for (i=0;i<nr;i++) { - ptr->next=(((void*)ptr)+size); - ptr=ptr->next; - } - ptr->next=0; - - ptr=__small_mem[idx]; - } - - /* get a free block */ - __small_mem[idx]=ptr->next; - ptr->next=0; - - smallalloc[idx]++; - if(smallalloc[idx] > smallalloc_max[idx]) - smallalloc_max[idx] = smallalloc[idx]; - - return ptr; -} - -/* -- PUBLIC FUNCTIONS ---------------------------------------------------- */ - -static void _alloc_libc_free(void *ptr) { - register size_t size; - if (ptr) { - size=((__alloc_t*)BLOCK_START(ptr))->size; - if (size) { - if (size<=__MAX_SMALL_SIZE) - __small_free(ptr,size); - else - munmap(BLOCK_START(ptr),size); - } - } -} -void __libc_free(void *ptr) __attribute__((alias("_alloc_libc_free"))); -void free(void *ptr) __attribute__((weak,alias("_alloc_libc_free"))); -void if_freenameindex(void* ptr) __attribute__((alias("free"))); - -#ifdef WANT_MALLOC_ZERO -static __alloc_t zeromem[2]; -#endif - -static void* _alloc_libc_malloc(size_t size) { - __alloc_t* ptr; - size_t need; -#ifdef WANT_MALLOC_ZERO - if (!size) return BLOCK_RET(zeromem); -#else - if (!size) goto err_out; -#endif - size+=sizeof(__alloc_t); - if (size<sizeof(__alloc_t)) goto err_out; - if (size<=__MAX_SMALL_SIZE) { - need=GET_SIZE(size); - ptr=__small_malloc(need); - } - else { - need=PAGE_ALIGN(size); - if (!need) ptr=MAP_FAILED; else ptr=do_mmap(need); - } - if (ptr==MAP_FAILED) goto err_out; - ptr->size=need; - return BLOCK_RET(ptr); -err_out: - (*__errno_location())=ENOMEM; - return 0; -} -void* __libc_malloc(size_t size) __attribute__((alias("_alloc_libc_malloc"))); -void* malloc(size_t size) __attribute__((weak,alias("_alloc_libc_malloc"))); - -void* __libc_calloc(size_t nmemb, size_t _size); -void* __libc_calloc(size_t nmemb, size_t _size) { - register size_t size=_size*nmemb; - if (nmemb && size/nmemb!=_size) { - (*__errno_location())=ENOMEM; - return 0; - } - return malloc(size); -} -void* calloc(size_t nmemb, size_t _size) __attribute__((weak,alias("__libc_calloc"))); - -void* __libc_realloc(void* ptr, size_t _size); -void* __libc_realloc(void* ptr, size_t _size) { - register size_t size=_size; - if (ptr) { - if (size) { - __alloc_t* tmp=BLOCK_START(ptr); - size+=sizeof(__alloc_t); - if (size<sizeof(__alloc_t)) goto retzero; - size=(size<=__MAX_SMALL_SIZE)?GET_SIZE(size):PAGE_ALIGN(size); - if (tmp->size!=size) { - if ((tmp->size<=__MAX_SMALL_SIZE)) { - void *new=_alloc_libc_malloc(_size); - if (new) { - register __alloc_t* foo=BLOCK_START(new); - size=foo->size; - if (size>tmp->size) size=tmp->size; - if (size) memcpy(new,ptr,size-sizeof(__alloc_t)); - _alloc_libc_free(ptr); - } - ptr=new; - } - else { - register __alloc_t* foo; - size=PAGE_ALIGN(size); - foo=mremap(tmp,tmp->size,size,MREMAP_MAYMOVE); - if (foo==MAP_FAILED) { -retzero: - (*__errno_location())=ENOMEM; - ptr=0; - } - else { - foo->size=size; - ptr=BLOCK_RET(foo); - } - } - } - } - else { /* size==0 */ - _alloc_libc_free(ptr); - ptr = NULL; - } - } - else { /* ptr==0 */ - if (size) { - ptr=_alloc_libc_malloc(size); - } - } - return ptr; -} -void* realloc(void* ptr, size_t size) __attribute__((weak,alias("__libc_realloc"))); - diff --git a/mbbsd/announce.c b/mbbsd/announce.c deleted file mode 100644 index fb7db427..00000000 --- a/mbbsd/announce.c +++ /dev/null @@ -1,1558 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -// XXX piaip 2007/12/29 -// ³Ìªñµo²{«Ü¦h code ³£¦º¦b announce -// ¦]¬°¶i¨Ón¬Ý lastlevel ¦Ó«D currbid -// user ¥i¯à¤@¶i BBS ª½±þ¶l¥ó->mail_cite->¶iºëµØ°Ï -// ©ó¬O´NÃz¬µ -// ¦P²z currboard ¤]¤£¸Ó¥Î -// ½Ð§ï¥Î me.bid (ª`·N me.bid ¥i¯à¬° 0, ªí¥Ü¶i¨Óªº«D¬ÝªO¡C) -// -// XXX 9999 ³Â·Ð·QӤ覡§ï±¼ - -// for max file size limitation here, see edit.c -#define MAX_FILE_SIZE (32768*1024) - -/* copy temp queue operation -------------------------------------- */ - -/* TODO - * change this to char* instead of char[] - */ -typedef struct { - char copyfile[PATHLEN]; - char copytitle[TTLEN + 1]; - char copyowner[IDLEN + 2]; -} CopyQueue ; - -#define COPYQUEUE_COMMON_SIZE (10) - -static CopyQueue *copyqueue; -static int allocated_copyqueue = 0, used_copyqueue = 0, head_copyqueue = 0; - -int copyqueue_testin(CopyQueue *pcq) -{ - int i = 0; - for (i = head_copyqueue; i < used_copyqueue; i++) - if (strcmp(pcq->copyfile, copyqueue[i].copyfile) == 0) - return 1; - return 0; -} - -int copyqueue_locate(CopyQueue *pcq) -{ - int i = 0; - for (i = head_copyqueue; i < used_copyqueue; i++) - if (strcmp(pcq->copyfile, copyqueue[i].copyfile) == 0) - return i; - return -1; -} - -int copyqueue_fileinqueue(const char *fn) -{ - int i = 0; - for (i = head_copyqueue; i < used_copyqueue; i++) - if (strcmp(fn, copyqueue[i].copyfile) == 0) - return 1; - return 0; -} - -void copyqueue_reset() -{ - allocated_copyqueue = 0; - used_copyqueue = 0; - head_copyqueue = 0; -} - -int copyqueue_append(CopyQueue *pcq) -{ - if(copyqueue_testin(pcq)) - return 0; - if(head_copyqueue == used_copyqueue) - { - // empty queue, happy happy reset - if(allocated_copyqueue > COPYQUEUE_COMMON_SIZE) - { - // let's reduce it - allocated_copyqueue = COPYQUEUE_COMMON_SIZE; - copyqueue = (CopyQueue*)realloc( copyqueue, - allocated_copyqueue * sizeof(CopyQueue)); - } - head_copyqueue = used_copyqueue = 0; - } - used_copyqueue ++; - - if(used_copyqueue > allocated_copyqueue) - { - allocated_copyqueue = - used_copyqueue + COPYQUEUE_COMMON_SIZE; // half page - copyqueue = (CopyQueue*) realloc (copyqueue, - sizeof(CopyQueue) * allocated_copyqueue); - if(!copyqueue) - { - vmsg("°O¾ÐÅ餣¨¬¡A«þ¨©¥¢±Ñ"); - // try to reset - copyqueue_reset(); - if(copyqueue) free(copyqueue); - copyqueue = NULL; - return 0; - } - } - memcpy(&(copyqueue[used_copyqueue-1]), pcq, sizeof(CopyQueue)); - return 1; -} - -int copyqueue_toggle(CopyQueue *pcq) -{ - int i = copyqueue_locate(pcq); - if(i >= 0) - { -#if 0 - if (getans("¤w¼Ð°O¹L¦¹ÀÉ¡An¨ú®ø¼Ð°O¶Ü [y/N]: ") != 'y') - return 1; -#endif - /* remove it */ - used_copyqueue --; - if(head_copyqueue > used_copyqueue) - head_copyqueue =used_copyqueue; - if (i < used_copyqueue) - { - memcpy(copyqueue + i, copyqueue+i+1, - sizeof(CopyQueue) * (used_copyqueue - i)); - } - return 0; - } else { - copyqueue_append(pcq); - } - return 1; -} - -CopyQueue *copyqueue_gethead() -{ - if( used_copyqueue <= 0 || - head_copyqueue >= used_copyqueue) - return NULL; - return &(copyqueue[head_copyqueue++]); -} - -int copyqueue_querysize() -{ - if( used_copyqueue <= 0 || - head_copyqueue >= used_copyqueue) - return 0; - return (used_copyqueue - head_copyqueue); -} - -/* end copy temp queue operation ----------------------------------- */ - -void -a_copyitem(const char *fpath, const char *title, const char *owner, int mode) -{ - CopyQueue cq; - static int flFirstAlert = 1; - - memset(&cq, 0, sizeof(CopyQueue)); - strcpy(cq.copyfile, fpath); - strcpy(cq.copytitle, title); - if (owner) - strcpy(cq.copyowner, owner); - - //copyqueue_append(&cq); - copyqueue_toggle(&cq); - if (mode && flFirstAlert) { -#if 0 - move(b_lines-2, 0); clrtoeol(); - prints("¥Ø«e¤w¼Ð°O %d ÓÀɮסC[ª`·N] «þ¨©«á¤~¯à§R°£ì¤å!", - copyqueue_querysize()); -#else - vmsg("[ª`·N] ´£¿ô±z½Æ»s/¼Ð°O«án¶K¤W(p)©Îªþ¥[(a)«á¤~¯à§R°£ì¤å!"); - flFirstAlert = 0; -#endif - } -} - -#define FHSZ sizeof(fileheader_t) - -static int -a_loadname(menu_t * pm) -{ - char buf[PATHLEN]; - int len; - - if(p_lines != pm->header_size) { - pm->header_size = p_lines; - pm->header = (fileheader_t *) realloc(pm->header, pm->header_size*FHSZ); - assert(pm->header); - } - - setadir(buf, pm->path); - len = get_records(buf, pm->header, FHSZ, pm->page + 1, pm->header_size); // XXX if get_records() return -1 - - // if len < 0, the directory is not valid anymore. - if (len < 0) - return 0; - - if (len < pm->header_size) - bzero(&pm->header[len], FHSZ * (pm->header_size - len)); - return 1; -} - -static void -a_timestamp(char *buf, const time4_t *time) -{ - struct tm *pt = localtime4(time); - - sprintf(buf, "%02d/%02d/%02d", pt->tm_mon + 1, pt->tm_mday, (pt->tm_year + 1900) % 100); -} - -static int -a_showmenu(menu_t * pm) -{ - char *title, *editor; - int n; - fileheader_t *item; - time4_t dtime; - - showtitle("ºëµØ¤å³¹", pm->mtitle); - prints(" " ANSI_COLOR(1;36) "½s¸¹ ¼Ð ÃD%56s" ANSI_COLOR(0), - "½s ¿ï ¤é ´Á"); - - if (!pm->num) - { - outs("\n ¡mºëµØ°Ï¡n©|¦b§l¨ú¤Ñ¦a¶¡ªº¤é¤ëºëµØ¤¤... :)"); - } - else - { - char buf[PATHLEN]; - - // determine if path is valid. - if (!a_loadname(pm)) - return 0; - - for (n = 0; n < p_lines && pm->page + n < pm->num; n++) { - int flTagged = 0; - item = &pm->header[n]; - title = item->title; - editor = item->owner; - /* - * Ptt §â®É¶¡§ï¬°¨úÀɮ׮ɶ¡ dtime = atoi(&item->filename[2]); - */ - snprintf(buf, sizeof(buf), "%s/%s", pm->path, item->filename); - if(copyqueue_querysize() > 0 && copyqueue_fileinqueue(buf)) - { - flTagged = 1; - } - dtime = dasht(buf); - a_timestamp(buf, &dtime); - prints("\n%6d%c%c%-47.46s%-13s[%s]", pm->page + n + 1, - (item->filemode & FILE_BM) ? 'X' : - (item->filemode & FILE_HIDE) ? ')' : '.', - flTagged ? 'c' : ' ', - title, editor, - buf); - } - } - - move(b_lines, 0); - if(copyqueue_querysize() > 0) - { // something in queue - prints( - ANSI_COLOR(37;44) "¡i¤w¼Ð°O(½Æ»s) %d ¶µ¡j" - ANSI_COLOR(31;47) " (c)" ANSI_COLOR(30) "¼Ð°O/½Æ»s " - , copyqueue_querysize()); - - if(pm->level == 0) - outs(" - µLºÞ²zÅv¡AµLªk¶K¤W " ANSI_RESET); - else - outs( ANSI_COLOR(31) "(p)" ANSI_COLOR(30) "¶K¤W/¨ú®ø/«³]¼Ð°O " - ANSI_COLOR(31) "(a)" ANSI_COLOR(30) "ªþ¥[¦Ü¤å³¹«á " - ANSI_RESET); - } - else if(pm->level) - { // BM - outs( - ANSI_COLOR(34;46) " ¡iªO ¥D¡j " - ANSI_COLOR(31;47) " (h)" ANSI_COLOR(30) "»¡©ú " - ANSI_COLOR(31) "(q/¡ö)" ANSI_COLOR(30) "Â÷¶} " - ANSI_COLOR(31) "(n)" ANSI_COLOR(30) "·s¼W¤å³¹ " - ANSI_COLOR(31) "(g)" ANSI_COLOR(30) "·s¼W¥Ø¿ý " - ANSI_COLOR(31) "(e)" ANSI_COLOR(30) "½s¿èÀÉ®× " ANSI_RESET - ); - } - else - { // normal user - outs( - ANSI_COLOR(34;46) " ¡i¥\\¯àÁä¡j " - ANSI_COLOR(31;47) " (h)" ANSI_COLOR(30) "»¡©ú " - ANSI_COLOR(31) "(q/¡ö)" ANSI_COLOR(30) "Â÷¶} " - ANSI_COLOR(31) "(k¡ôj¡õ)" ANSI_COLOR(30) "²¾°Ê´å¼Ð " - ANSI_COLOR(31) "(enter/¡÷)" ANSI_COLOR(30) "Ū¨ú¸ê®Æ " ANSI_RESET); - } - return 1; -} - -static int -a_searchtitle(menu_t * pm, int rev) -{ - static char search_str[40] = ""; - int pos; - - getdata(b_lines - 1, 1, "[·j´M]ÃöÁä¦r:", search_str, sizeof(search_str), DOECHO); - - if (!*search_str) - return pm->now; - - str_lower(search_str, search_str); - - rev = rev ? -1 : 1; - pos = pm->now; - do { - pos += rev; - if (pos == pm->num) - pos = 0; - else if (pos < 0) - pos = pm->num - 1; - if (pos < pm->page || pos >= pm->page + p_lines) { - pm->page = pos - pos % p_lines; - - if (!a_loadname(pm)) - return pm->now; - } - if (strcasestr(pm->header[pos - pm->page].title, search_str)) - return pos; - } while (pos != pm->now); - return pm->now; -} - -enum { - NOBODY, MANAGER, SYSOP -}; - -static void -a_showhelp(int level) -{ - clear(); - outs(ANSI_COLOR(36) "¡i " BBSNAME "¤½§GÄæ¨Ï¥Î»¡©ú ¡j" ANSI_RESET "\n\n" - "[¡ö][q] Â÷¶}¨ì¤W¤@¼h¥Ø¿ý\n" - "[¡ô][k] ¤W¤@ӿﶵ\n" - "[¡õ][j] ¤U¤@ӿﶵ\n" - "[¡÷][r][enter] ¶i¤J¥Ø¿ý¡þŪ¨ú¤å³¹\n" - "[^B][PgUp] ¤W¶¿ï³æ\n" - "[^F][PgDn][Spc] ¤U¶¿ï³æ\n" - "[##] ²¾¨ì¸Ó¿ï¶µ\n" - "[F][U] ±N¤å³¹±H¦^ Internet ¶l½c/" - "±N¤å³¹ uuencode «á±H¦^¶l½c\n"); - if (level >= MANAGER) { - outs("\n" ANSI_COLOR(36) "¡i ªO¥D±M¥ÎÁä ¡j" ANSI_RESET "\n" - "[H] ¤Á´«¬° ¤½¶}/·|û/ªO¥D ¤~¯à¾\\Ū\n" - "[n/g/G] ¦¬¿ýºëµØ¤å³¹/¶}ÅP¥Ø¿ý/«Ø¥ß³s½u\n" - "[m/d/D] ²¾°Ê/§R°£¤å³¹/§R°£¤@Ó½d³òªº¤å³¹\n" - "[f/T/e] ½s¿è¼ÐÃD²Å¸¹/קï¤å³¹¼ÐÃD/¤º®e\n" - "[c/p/a] ºëµØ°Ï¤º ¼Ð°O(½Æ»s)/¶K¤W(¥i¦h½g)/ªþ¥[³æ½g¤å³¹\n" - "[^P/^A] ¶K¤W/ªþ¥[ºëµØ°Ï¥~¤w¥Î't'¼Ð°O¤å³¹\n"); - } - if (level >= SYSOP) { - outs("\n" ANSI_COLOR(36) "¡i ¯¸ªø±M¥ÎÁä ¡j" ANSI_RESET "\n" - "[l] «Ø symbolic link\n" - "[N] ¬d¸ßÀɦW\n"); - } - pressanykey(); -} - -static void -a_forward(const char *path, const fileheader_t * pitem, int mode) -{ - fileheader_t fhdr; - - strlcpy(fhdr.filename, pitem->filename, sizeof(fhdr.filename)); - strlcpy(fhdr.title, pitem->title, sizeof(fhdr.title)); - switch (doforward(path, &fhdr, mode)) { - case 0: - outmsg(msg_fwd_ok); - break; - case -1: - outmsg(msg_fwd_err1); - break; - case -2: - outmsg(msg_fwd_err2); - break; - } -} - -static void -a_additem(menu_t * pm, const fileheader_t * myheader) -{ - char buf[PATHLEN]; - - setadir(buf, pm->path); - if (append_record(buf, myheader, FHSZ) == -1) - return; - pm->now = pm->num++; - - if (pm->now >= pm->page + p_lines) { - pm->page = pm->now - ((pm->page == 10000 && pm->now > p_lines / 2) ? - (p_lines / 2) : (pm->now % p_lines)); - } - /* Ptt */ - strlcpy(pm->header[pm->now - pm->page].filename, - myheader->filename, - sizeof(pm->header[pm->now - pm->page].filename)); -} - -#define ADDITEM 0 -#define ADDGROUP 1 - -static void -a_newitem(menu_t * pm, int mode) -{ - char *mesg[3] = { - "[·s¼W¤å³¹] ½Ð¿é¤J¼ÐÃD¡G", /* ADDITEM */ - "[·s¼W¥Ø¿ý] ½Ð¿é¤J¼ÐÃD¡G", /* ADDGROUP */ - }; - - char fpath[PATHLEN]; - fileheader_t item; - - strlcpy(fpath, pm->path, sizeof(fpath)); - if (strlen(pm->path) + FNLEN*2 >= PATHLEN) - return; - - switch (mode) { - case ADDITEM: - stampfile(fpath, &item); - strlcpy(item.title, "¡º ", sizeof(item.title)); /* A1BA */ - break; - - case ADDGROUP: - stampdir(fpath, &item); - strlcpy(item.title, "¡» ", sizeof(item.title)); /* A1BB */ - break; - } - - if (!getdata(b_lines - 1, 1, mesg[mode], &item.title[3], 55, DOECHO)) { - if (mode == ADDGROUP) - rmdir(fpath); - else - unlink(fpath); - return; - } - switch (mode) { - case ADDITEM: - { - int edflags = 0; -# ifdef GLOBAL_BBSMOVIE - if (pm && pm->bid && - strcmp(getbcache(pm->bid)->brdname, - GLOBAL_BBSMOVIE) == 0) - { - edflags |= EDITFLAG_UPLOAD; - edflags |= EDITFLAG_ALLOWLARGE; - } -# endif // GLOBAL_BBSMOVIE - if (vedit2(fpath, 0, NULL, edflags) == -1) { - unlink(fpath); - pressanykey(); - return; - } - } - break; - case ADDGROUP: - // do nothing - break; - } - - strlcpy(item.owner, cuser.userid, sizeof(item.owner)); - a_additem(pm, &item); -} - -void -a_pasteitem(menu_t * pm, int mode) -{ - char newpath[PATHLEN]; - char buf[PATHLEN]; - char ans[2], skipAll = 0, multiple = 0; - int i, copied = 0; - fileheader_t item; - - CopyQueue *cq; - - move(b_lines - 1, 0); - if(copyqueue_querysize() <= 0) - { - vmsg("½Ð¥ý°õ¦æ½Æ»s(copy)©R¥O«á¦A¶K¤W(paste)"); - return; - } - if(mode && copyqueue_querysize() > 1) - { - multiple = 1; - move(b_lines-2, 0); clrtobot(); - outs("c: ¹ï¦U¶µ¥ØÓ§O½T»{¬O§_n¶K¤W, z: ¥þ³¡¤£¶K¡A¦P®É«³]¨Ã¨ú®ø¥þ³¡¼Ð°O\n"); - snprintf(buf, sizeof(buf), - "½T©wn¶K¤W¥þ³¡¦@ %d Ó¶µ¥Ø¶Ü (c/z/y/N)¡H ", - copyqueue_querysize()); - getdata(b_lines - 1, 0, buf, ans, sizeof(ans), LCECHO); - if(ans[0] == 'y') - skipAll = 1; - else if(ans[0] == 'z') - { - copyqueue_reset(); - vmsg("¤w«³]½Æ»s°O¿ý¡C"); - return; - } - else if (ans[0] != 'c') - return; - clear(); - } - while (copyqueue_querysize() > 0) - { - cq = copyqueue_gethead(); - if(!cq->copyfile[0]) - continue; - if(mode && multiple) - { - scroll(); - move(b_lines-2, 0); clrtobot(); - prints("%d. %s\n", ++copied,cq->copytitle); - - } - - if (dashd(cq->copyfile)) { - for (i = 0; cq->copyfile[i] && cq->copyfile[i] == pm->path[i]; i++); - if (!cq->copyfile[i]) { - vmsg("±N¥Ø¿ý«þ¶i¦Û¤vªº¤l¥Ø¿ý¤¤¡A·|³y¦¨µL½a°j°é¡I"); - continue; - } - } - if (mode && !skipAll) { - snprintf(buf, sizeof(buf), - "½T©wn«þ¨©[%s]¶Ü(Y/N)¡H[N] ", cq->copytitle); - getdata(b_lines - 1, 0, buf, ans, sizeof(ans), LCECHO); - } else - ans[0] = 'y'; - if (ans[0] == 'y') { - strlcpy(newpath, pm->path, sizeof(newpath)); - - if (*cq->copyowner) { - char *fname = strrchr(cq->copyfile, '/'); - - if (fname) - strcat(newpath, fname); - else - return; - if (access(pm->path, X_OK | R_OK | W_OK)) - mkdir(pm->path, 0755); - memset(&item, 0, sizeof(fileheader_t)); - strlcpy(item.filename, fname + 1, sizeof(item.filename)); - memcpy(cq->copytitle, "¡·", 2); - Copy(cq->copyfile, newpath); - } else if (dashf(cq->copyfile)) { - stampfile(newpath, &item); - memcpy(cq->copytitle, "¡º", 2); - Copy(cq->copyfile, newpath); - } else if (dashd(cq->copyfile)) { - stampdir(newpath, &item); - memcpy(cq->copytitle, "¡»", 2); - copy_file(cq->copyfile, newpath); - } else { - copyqueue_reset(); - vmsg("µLªk«þ¨©¡I"); - return; - } - strlcpy(item.owner, *cq->copyowner ? cq->copyowner : cuser.userid, - sizeof(item.owner)); - strlcpy(item.title, cq->copytitle, sizeof(item.title)); - a_additem(pm, &item); - cq->copyfile[0] = '\0'; - } - } -} - -static void -a_appenditem(const menu_t * pm, int isask) -{ - char fname[PATHLEN]; - char buf[ANSILINELEN]; - char ans[2] = "y"; - FILE *fp, *fin; - - move(b_lines - 1, 0); - if(copyqueue_querysize() <= 0) - { - vmsg("½Ð¥ý°õ¦æ copy ©R¥O«á¦A append"); - copyqueue_reset(); - return; - } - else - { - CopyQueue *cq = copyqueue_gethead(); - off_t sz; - - if (!dashf(cq->copyfile)) { - vmsg("¥Ø¿ý¤£±oªþ¥[©óÀɮ׫á¡I"); - return; - } - - snprintf(fname, sizeof(fname), "%s/%s", pm->path, - pm->header[pm->now - pm->page].filename); - - if (!dashf(fname)) { - vmsg("Àɮפ£±oªþ¥[©ó¦¹¡I"); - return; - } - - sz = dashs(fname); - if (sz >= MAX_FILE_SIZE) - { - vmsg("Àɮפw¶W¹L³Ì¤j¨î¡AµLªk¦Aªþ¥["); - return; - } - - if (isask) { - snprintf(buf, sizeof(buf), - "½T©wn±N[%s]ªþ¥[©ó¦¹¶Ü(Y/N)¡H[N] ", cq->copytitle); - getdata(b_lines - 2, 1, buf, ans, sizeof(ans), LCECHO); - } - - if (ans[0] != 'y' || !(fp = fopen(fname, "a+"))) - return; - - if (!(fin = fopen(cq->copyfile, "r"))) { - fclose(fp); - return; - } - - memset(buf, '-', 74); - buf[74] = '\0'; - fprintf(fp, "\n> %s <\n\n", buf); - if (isask) - getdata(b_lines - 1, 1, - "¬O§_¦¬¿ýñ¦WÀɳ¡¥÷(Y/N)¡H[Y] ", - ans, sizeof(ans), LCECHO); - - while (fgets(buf, sizeof(buf), fin)) { - if ((ans[0] == 'n') && - !strcmp(buf, "--\n")) - break; - fputs(buf, fp); - } - fclose(fin); - fclose(fp); - cq->copyfile[0] = '\0'; - } -} - -static int -a_pastetagpost(menu_t * pm, int mode) -{ - fileheader_t fhdr; - boardheader_t *bh = NULL; - int ans = 0, ent = 0, tagnum; - char title[TTLEN + 1] = "¡º "; - char dirname[PATHLEN], buf[PATHLEN]; - - if (TagBoard == 0){ - sethomedir(dirname, cuser.userid); - } - else{ - bh = getbcache(TagBoard); - setbdir(dirname, bh->brdname); - } - tagnum = TagNum; - - // prevent if anything wrong - if (tagnum > MAXTAGS || tagnum < 0) - { - vmsg("¤º³¡¿ù»~¡C½Ð§â§Aèè¶i¦æªº§¹¾ã¨BÆJ¶K¨ì " - GLOBAL_BUGREPORT " ªO¡C"); - return ans; - } - - if (tagnum < 1) - return ans; - - /* since we use different tag features, - * copyqueue is not required/used. */ - copyqueue_reset(); - - while (tagnum-- > 0) { - memset(&fhdr, 0, sizeof(fhdr)); - EnumTagFhdr(&fhdr, dirname, ent++); - - // XXX many process crashed here as fhdr.filename[0] == 0 - // let's workaround it? or trace? - // if (!fhdr->filename[0]) - // continue; - - if (!fhdr.filename[0]) - { - grayout(0, b_lines-2, GRAYOUT_DARK); - move(b_lines-1, 0); clrtobot(); - prints("²Ä %d ¶µ³B²zµo¥Í¿ù»~¡C ½Ð§â§Aèè¶i¦æªº§¹¾ã¨BÆJ¶K¨ì " - GLOBAL_BUGREPORT " ªO¡C\n", ent); - vmsg("©¿²¤¿ù»~¨ÃÄ~Äò¶i¦æ¡C"); - continue; - } - - if (TagBoard == 0) - sethomefile(buf, cuser.userid, fhdr.filename); - else - setbfile(buf, bh->brdname, fhdr.filename); - - if (dashf(buf)) { - strlcpy(title + 3, fhdr.title, sizeof(title) - 3); - a_copyitem(buf, title, 0, 0); - if (mode) { - mode--; - a_pasteitem(pm, 0); - } else - a_appenditem(pm, 0); - ++ans; - UnTagger(tagnum); - } - } - - return ans; -} - -static void -a_moveitem(menu_t * pm) -{ - fileheader_t *tmp; - char newnum[5]; - int num, max, min; - char buf[PATHLEN]; - int fail; - - snprintf(buf, sizeof(buf), "½Ð¿é¤J²Ä %d ¿ï¶µªº·s¦¸§Ç¡G", pm->now + 1); - if (!getdata(b_lines - 1, 1, buf, newnum, sizeof(newnum), DOECHO)) - return; - num = (newnum[0] == '$') ? 9999 : atoi(newnum) - 1; - if (num >= pm->num) - num = pm->num - 1; - else if (num < 0) - num = 0; - setadir(buf, pm->path); - min = num < pm->now ? num : pm->now; - max = num > pm->now ? num : pm->now; - tmp = (fileheader_t *) calloc(max + 1, FHSZ); - - fail = 0; - if (get_records(buf, tmp, FHSZ, 1, min) != min) - fail = 1; - if (num > pm->now) { - if (get_records(buf, &tmp[min], FHSZ, pm->now + 2, max - min) != max - min) - fail = 1; - if (get_records(buf, &tmp[max], FHSZ, pm->now + 1, 1) != 1) - fail = 1; - } else { - if (get_records(buf, &tmp[min], FHSZ, pm->now + 1, 1) != 1) - fail = 1; - if (get_records(buf, &tmp[min + 1], FHSZ, num + 1, max - min) != max - min) - fail = 1; - } - if (!fail) - substitute_record(buf, tmp, FHSZ * (max + 1), 1); - pm->now = num; - free(tmp); -} - -static void -a_delrange(menu_t * pm) -{ - char fname[PATHLEN]; - - snprintf(fname, sizeof(fname), "%s/" FN_DIR, pm->path); - del_range(0, NULL, fname); - pm->num = get_num_records(fname, FHSZ); -} - -static void -a_delete(menu_t * pm) -{ - char fpath[PATHLEN], buf[PATHLEN], cmd[PATHLEN]; - char ans[4]; - fileheader_t backup; - - snprintf(fpath, sizeof(fpath), - "%s/%s", pm->path, pm->header[pm->now - pm->page].filename); - setadir(buf, pm->path); - - if (pm->header[pm->now - pm->page].filename[0] == 'H' && - pm->header[pm->now - pm->page].filename[1] == '.') { - getdata(b_lines - 1, 1, "±z½T©wn§R°£¦¹ºëµØ°Ï³s½u¶Ü(Y/N)¡H[N] ", - ans, sizeof(ans), LCECHO); - if (ans[0] != 'y') - return; - if (delete_record(buf, FHSZ, pm->now + 1) == -1) - return; - } else if (dashl(fpath)) { - getdata(b_lines - 1, 1, "±z½T©wn§R°£¦¹ symbolic link ¶Ü(Y/N)¡H[N] ", - ans, sizeof(ans), LCECHO); - if (ans[0] != 'y') - return; - if (delete_record(buf, FHSZ, pm->now + 1) == -1) - return; - unlink(fpath); - } else if (dashf(fpath)) { - getdata(b_lines - 1, 1, "±z½T©wn§R°£¦¹Àɮ׶Ü(Y/N)¡H[N] ", ans, - sizeof(ans), LCECHO); - if (ans[0] != 'y') - return; - if (delete_record(buf, FHSZ, pm->now + 1) == -1) - return; - - setbpath(buf, "deleted"); - stampfile(buf, &backup); - strlcpy(backup.owner, cuser.userid, sizeof(backup.owner)); - strlcpy(backup.title, - pm->header[pm->now - pm->page].title + 2, - sizeof(backup.title)); - - snprintf(cmd, sizeof(cmd), - "mv -f %s %s", fpath, buf); - system(cmd); - setbdir(buf, "deleted"); - append_record(buf, &backup, sizeof(backup)); - } else if (dashd(fpath)) { - getdata(b_lines - 1, 1, "±z½T©wn§R°£¾ãӥؿý¶Ü(Y/N)¡H[N] ", ans, - sizeof(ans), LCECHO); - if (ans[0] != 'y') - return; - if (delete_record(buf, FHSZ, pm->now + 1) == -1) - return; - - setapath(buf, "deleted"); - stampdir(buf, &backup); - - snprintf(cmd, sizeof(cmd), - "rm -rf %s;/bin/mv -f %s %s", buf, fpath, buf); - system(cmd); - - strlcpy(backup.owner, cuser.userid, sizeof(backup.owner)); - strcpy(backup.title, "¡»"); - strlcpy(backup.title + 2, - pm->header[pm->now - pm->page].title + 2, - sizeof(backup.title) - 3); - - /* merge setapath(buf, "deleted"); setadir(buf, buf); */ - snprintf(buf, sizeof(buf), "man/boards/%c/%s/" FN_DIR, - 'd', "deleted"); - append_record(buf, &backup, sizeof(backup)); - } else { /* Ptt ·l·´ªº¶µ¥Ø */ - getdata(b_lines - 1, 1, "±z½T©wn§R°£¦¹·l·´ªº¶µ¥Ø¶Ü(Y/N)¡H[N] ", - ans, sizeof(ans), LCECHO); - if (ans[0] != 'y') - return; - if (delete_record(buf, FHSZ, pm->now + 1) == -1) - return; - } - pm->num--; -} - -static void -a_newtitle(const menu_t * pm) -{ - char buf[PATHLEN]; - fileheader_t item; - - memcpy(&item, &pm->header[pm->now - pm->page], FHSZ); - strlcpy(buf, item.title + 3, sizeof(buf)); - if (getdata_buf(b_lines - 1, 1, "·s¼ÐÃD¡G", buf, 60, DOECHO)) { - strlcpy(item.title + 3, buf, sizeof(item.title) - 3); - setadir(buf, pm->path); - substitute_record(buf, &item, FHSZ, pm->now + 1); - } -} -static void -a_hideitem(const menu_t * pm) -{ - fileheader_t *item = &pm->header[pm->now - pm->page]; - char buf[PATHLEN]; - if (item->filemode & FILE_BM) { - item->filemode &= ~FILE_BM; - item->filemode &= ~FILE_HIDE; - } else if (item->filemode & FILE_HIDE) - item->filemode |= FILE_BM; - else - item->filemode |= FILE_HIDE; - setadir(buf, pm->path); - substitute_record(buf, item, FHSZ, pm->now + 1); -} -static void -a_editsign(const menu_t * pm) -{ - char buf[PATHLEN]; - fileheader_t item; - - memcpy(&item, &pm->header[pm->now - pm->page], FHSZ); - snprintf(buf, sizeof(buf), "%c%c", item.title[0], item.title[1]); - if (getdata_buf(b_lines - 1, 1, "²Å¸¹", buf, 5, DOECHO)) { - item.title[0] = buf[0] ? buf[0] : ' '; - item.title[1] = buf[1] ? buf[1] : ' '; - item.title[2] = buf[2] ? buf[2] : ' '; - setadir(buf, pm->path); - substitute_record(buf, &item, FHSZ, pm->now + 1); - } -} - -static void -a_showname(const menu_t * pm) -{ - char buf[PATHLEN]; - int len; - int i; - int sym; - - move(b_lines - 1, 0); - snprintf(buf, sizeof(buf), - "%s/%s", pm->path, pm->header[pm->now - pm->page].filename); - if (dashl(buf)) { - prints("¦¹ symbolic link ¦WºÙ¬° %s\n", - pm->header[pm->now - pm->page].filename); - if ((len = readlink(buf, buf, PATHLEN - 1)) >= 0) { - buf[len] = '\0'; - for (i = 0; BBSHOME[i] && buf[i] == BBSHOME[i]; i++); - if (!BBSHOME[i] && buf[i] == '/') { - if (HasUserPerm(PERM_BBSADM)) - sym = 1; - else { - sym = 0; - for (i++; BBSHOME "/man"[i] && buf[i] == BBSHOME "/man"[i]; - i++); - if (!BBSHOME "/man"[i] && buf[i] == '/') - sym = 1; - } - if (sym) { - vmsgf("¦¹ symbolic link «ü¦V %s\n", &buf[i + 1]); - } - } - } - } else if (dashf(buf)) - prints("¦¹¤å³¹¦WºÙ¬° %s", pm->header[pm->now - pm->page].filename); - else if (dashd(buf)) - prints("¦¹¥Ø¿ý¦WºÙ¬° %s", pm->header[pm->now - pm->page].filename); - else - outs("¦¹¶µ¥Ø¤w·l·´, «Øij±N¨ä§R°£¡I"); - pressanykey(); -} -#ifdef CHESSCOUNTRY -static void -a_setchesslist(const menu_t * me) -{ - char buf[4]; - char buf_list[PATHLEN]; - char buf_photo[PATHLEN]; - char buf_this[PATHLEN]; - char buf_real[PATHLEN]; - int list_exist, photo_exist; - fileheader_t* fhdr = me->header + me->now - me->page; - int n; - - snprintf(buf_this, sizeof(buf_this), "%s/%s", me->path, fhdr->filename); - if((n = readlink(buf_this, buf_real, sizeof(buf_real) - 1)) == -1) - strcpy(buf_real, fhdr->filename); - else - // readlink doesn't garentee zero-ended - buf_real[n] = 0; - - if (strcmp(buf_real, "chess_list") == 0 - || strcmp(buf_real, "chess_photo") == 0) { - vmsg("¤£»Ý«³]¡I"); - return; - } - - snprintf(buf_list, sizeof(buf_list), "%s/chess_list", me->path); - snprintf(buf_photo, sizeof(buf_photo), "%s/chess_photo", me->path); - - list_exist = dashf(buf_list); - photo_exist = dashd(buf_photo); - - if (!list_exist && !photo_exist) { - vmsg("¦¹¬ÝªO«D´Ñ°ê¡I"); - return; - } - - getdata(b_lines, 0, "±N¦¹¶µ¥Ø³]©w¬° (1) ´Ñ°ê¦W³æ (2) ´Ñ°ê·Ó¤ùÀɥؿý¡G", - buf, sizeof(buf), 1); - if (buf[0] == '1') { - if (list_exist) - getdata(b_lines, 0, "즳¤§´Ñ°ê¦W³æ±N³Q¨ú¥N¡A½Ð½T»{ (y/N)", - buf, sizeof(buf), 1); - else - buf[0] = 'y'; - - if (buf[0] == 'y' || buf[0] == 'Y') { - Rename(buf_this, buf_list); - symlink("chess_list", buf_this); - } - } else if (buf[0] == '2') { - if (photo_exist) - getdata(b_lines, 0, "즳¤§´Ñ°ê·Ó¤ù±N³Q¨ú¥N¡A½Ð½T»{ (y/N)", - buf, sizeof(buf), 1); - else - buf[0] = 'y'; - - if (buf[0] == 'y' || buf[0] == 'Y') { - if(strncmp(buf_photo, "man/boards/", 11) == 0 && // guarding - buf_photo[11] && buf_photo[12] == '/' && // guarding - snprintf(buf_list, sizeof(buf_list), "rm -rf %s", buf_photo) - == strlen(buf_photo) + 7) - system(buf_list); - Rename(buf_this, buf_photo); - symlink("chess_photo", buf_this); - } - } -} -#endif /* defined(CHESSCOUNTRY) */ - -static int -isvisible_man(const menu_t * me) -{ - fileheader_t *fhdr = &me->header[me->now - me->page]; - /* board friend only effact when in board reading mode */ - if (me->level >= MANAGER) - return 1; - if (fhdr->filemode & FILE_BM) - return 0; - if (fhdr->filemode & FILE_HIDE) - { - if (currstat == ANNOUNCE || - !is_hidden_board_friend(me->bid, currutmp->uid)) - return 0; - } - return 1; -} -int -a_menu(const char *maintitle, const char *path, - int lastlevel, int lastbid, - char *trans_buffer) -{ - static char Fexit; // ¥Î¨Ó¸õ¥X recursion - menu_t me; - char fname[PATHLEN]; - int ch, returnvalue = FULLUPDATE; - - // prevent deep resursive directories - if (strlen(path) + FNLEN >= PATHLEN) - { - // it is not save to enter such directory. - return returnvalue; - } - - if(trans_buffer) - trans_buffer[0] = '\0'; - - memset(&me, 0, sizeof(me)); - Fexit = 0; - me.header_size = p_lines; - me.header = (fileheader_t *) calloc(me.header_size, FHSZ); - me.path = path; - strlcpy(me.mtitle, maintitle, sizeof(me.mtitle)); - setadir(fname, me.path); - me.num = get_num_records(fname, FHSZ); - me.bid = lastbid; - - /* ºëµØ°Ï-tree ¤¤³¡¥÷µ²ºcÄÝ©ó cuser ==> BM */ - - if (!(me.level = lastlevel)) { - char *ptr; - - if ((ptr = strrchr(me.mtitle, '['))) - me.level = is_BM(ptr + 1); - } - me.page = 9999; - me.now = 0; - for (;;) { - if (me.now >= me.num) - me.now = me.num - 1; - if (me.now < 0) - me.now = 0; - - if (me.now < me.page || me.now >= me.page + me.header_size) { - me.page = me.now - ((me.page == 10000 && me.now > p_lines / 2) ? - (p_lines / 2) : (me.now % p_lines)); - if (!a_showmenu(&me)) - { - // some directories are invalid, restart! - Fexit = 1; - break; - } - } - ch = cursor_key(2 + me.now - me.page, 0); - - if (ch == 'q' || ch == 'Q' || ch == KEY_LEFT) - break; - - if (ch >= '1' && ch <= '9') { - if ((ch = search_num(ch, me.num)) != -1) - me.now = ch; - me.page = 10000; - continue; - } - switch (ch) { - case KEY_UP: - case 'k': - if (--me.now < 0) - me.now = me.num - 1; - break; - - case KEY_DOWN: - case 'j': - if (++me.now >= me.num) - me.now = 0; - break; - - case KEY_PGUP: - case Ctrl('B'): - if (me.now >= p_lines) - me.now -= p_lines; - else if (me.now > 0) - me.now = 0; - else - me.now = me.num - 1; - break; - - case ' ': - case KEY_PGDN: - case Ctrl('F'): - if (me.now < me.num - p_lines) - me.now += p_lines; - else if (me.now < me.num - 1) - me.now = me.num - 1; - else - me.now = 0; - break; - - case '0': - me.now = 0; - break; - case '?': - case '/': - if(me.num) { - me.now = a_searchtitle(&me, ch == '?'); - me.page = 9999; - } - break; - case '$': - me.now = me.num - 1; - break; - case 'h': - a_showhelp(me.level); - me.page = 9999; - break; - - case Ctrl('I'): - t_idle(); - me.page = 9999; - break; - - case 'e': - case 'E': - snprintf(fname, sizeof(fname), - "%s/%s", path, me.header[me.now - me.page].filename); - if (dashf(fname) && me.level >= MANAGER) { - int edflags = 0; - *quote_file = 0; - -# ifdef GLOBAL_BBSMOVIE - if (me.bid && strcmp(getbcache(me.bid)->brdname, - GLOBAL_BBSMOVIE) == 0) - { - edflags |= EDITFLAG_UPLOAD; - edflags |= EDITFLAG_ALLOWLARGE; - } -# endif // GLOBAL_BBSMOVIE - - if (vedit2(fname, NA, NULL, edflags) != -1) { - char fpath[PATHLEN]; - fileheader_t fhdr; - strlcpy(fpath, path, sizeof(fpath)); - stampfile(fpath, &fhdr); - unlink(fpath); - strlcpy(fhdr.filename, - me.header[me.now - me.page].filename, - sizeof(fhdr.filename)); - strlcpy(me.header[me.now - me.page].owner, - cuser.userid, - sizeof(me.header[me.now - me.page].owner)); - setadir(fpath, path); - substitute_record(fpath, me.header + me.now - me.page, - sizeof(fhdr), me.now + 1); - - } - me.page = 9999; - } - break; - - case 't': - case 'c': - if (me.now < me.num) { - if (!isvisible_man(&me)) - break; - - snprintf(fname, sizeof(fname), "%s/%s", path, - me.header[me.now - me.page].filename); - - /* XXX: dirty fix - À³¸Ón§ï¦¨¦pªGµo²{¸Ó¥Ø¿ý¸Ì±¦³Áô§Î¥Ø¿ýªº¸Ü¤~©Úµ´. - ¤£¹L³o¼Ëªº¸Ü¶·n¾ãÓ·j¤@¹M, ¦Ó¥B¥Ø«e§PÂ_¸Ó¸ê®Æ¬O¥Ø¿ý - ÁÙ¬OÀɮ׳ºµM¬O¥Î fstat(2) ¦Ó¤£¬Oª½±µ¦s¦b .DIR ¤º |||b - ¶·µ¥¸Ó¸ê®Æ¼g¤J .DIR ¤º¦A implement¤~¦³®Ä²v. - */ - if( !lastlevel && !HasUserPerm(PERM_SYSOP) && - (me.bid==0 || !is_BM_cache(me.bid)) && dashd(fname) ) - vmsg("¥u¦³ªO¥D¤~¥i¥H«þ¨©¥Ø¿ýò!"); - else - a_copyitem(fname, me.header[me.now - me.page].title, 0, 1); - me.page = 9999; - /* move down */ - if (++me.now >= me.num) - me.now = 0; - break; - } - case '\n': - case '\r': - case KEY_RIGHT: - case 'r': - if (me.now < me.num) { - fileheader_t *fhdr = &me.header[me.now - me.page]; - if (!isvisible_man(&me)) - break; -#ifdef DEBUG - vmsgf("%s/%s", &path[11], fhdr->filename);; -#endif - snprintf(fname, sizeof(fname), "%s/%s", path, fhdr->filename); - if (*fhdr->filename == 'H' && fhdr->filename[1] == '.') { - vmsg("¤£¦A¤ä´© gopher mode, ½Ð¨Ï¥ÎÂsÄý¾¹ª½±µÂsÄý"); - vmsgf("gopher://%s/1/",fhdr->filename+2); - } else if (dashf(fname)) { - int more_result; - - while ((more_result = more(fname, YEA))) { - /* Ptt ½d¥»ºëÆF plugin */ - if (trans_buffer && - (currstat == EDITEXP || currstat == OSONG)) { - char ans[4]; - - move(22, 0); - clrtoeol(); - getdata(22, 1, - currstat == EDITEXP ? - "n§â½d¨Ò Plugin ¨ì¤å³¹¶Ü?[y/N]" : - "½T©wnÂI³oººq¶Ü?[y/N]", - ans, sizeof(ans), LCECHO); - if (ans[0] == 'y') { - strlcpy(trans_buffer, fname, PATHLEN); - Fexit = 1; - if (currstat == OSONG) { - log_filef(FN_USSONG, LOG_CREAT, "%s\n", fhdr->title); - } - free(me.header); - return FULLUPDATE; - } - } - if (more_result == READ_PREV) { - if (--me.now < 0) { - me.now = 0; - break; - } - } else if (more_result == READ_NEXT) { - if (++me.now >= me.num) { - me.now = me.num - 1; - break; - } - /* we only load me.header_size pages */ - if (me.now - me.page >= me.header_size) - break; - } else - break; - if (!isvisible_man(&me)) - break; - snprintf(fname, sizeof(fname), "%s/%s", path, - me.header[me.now - me.page].filename); - if (!dashf(fname)) - break; - } - } else if (dashd(fname)) { - a_menu(me.header[me.now - me.page].title, fname, - me.level, me.bid, trans_buffer); - /* Ptt ±j¤O¸õ¥Xrecursive */ - if (Fexit) { - free(me.header); - return FULLUPDATE; - } - } - me.page = 9999; - } - break; - - case 'F': - case 'U': - if (me.now < me.num) { - fileheader_t *fhdr = &me.header[me.now - me.page]; - if (!isvisible_man(&me)) - break; - snprintf(fname, sizeof(fname), - "%s/%s", path, fhdr->filename); - if (HasUserPerm(PERM_LOGINOK) && dashf(fname)) { - a_forward(path, fhdr, ch /* == 'U' */ ); - /* By CharlieL */ - } else - vmsg("µLªkÂà±H¦¹¶µ¥Ø"); - me.page = 9999; - } - - break; - - } - - if (me.level >= MANAGER) { - switch (ch) { - case 'n': - a_newitem(&me, ADDITEM); - me.page = 9999; - break; - case 'g': - a_newitem(&me, ADDGROUP); - me.page = 9999; - break; - case 'p': - a_pasteitem(&me, 1); - me.page = 9999; - break; - case 'f': - a_editsign(&me); - me.page = 9999; - break; - case Ctrl('P'): - a_pastetagpost(&me, -1); - returnvalue = DIRCHANGED; - me.page = 9999; - break; - case Ctrl('A'): - a_pastetagpost(&me, 1); - returnvalue = DIRCHANGED; - me.page = 9999; - break; - case 'a': - a_appenditem(&me, 1); - me.page = 9999; - break; -#ifdef BLOG - case 'b': - if (me.bid) - { - char genbuf[128]; - char *bname = getbcache(me.bid)->brdname; - snprintf(genbuf, sizeof(genbuf), - "bin/builddb.pl -f -n %d %s", me.now, bname); - system(genbuf); - vmsg("¸ê®Æ§ó·s§¹¦¨"); - } - me.page = 9999; - break; - - case 'B': - if (me.bid && me.bid == currbid) - { - BlogMain(me.now); - }; - me.page = 9999; - break; -#endif - } - - if (me.num) - switch (ch) { - case 'm': - a_moveitem(&me); - me.page = 9999; - break; - - case 'D': - /* Ptt me.page = -1; */ - a_delrange(&me); - me.page = 9999; - break; - case 'd': - a_delete(&me); - me.page = 9999; - break; - case 'H': - a_hideitem(&me); - me.page = 9999; - break; - case 'T': - a_newtitle(&me); - me.page = 9999; - break; -#ifdef CHESSCOUNTRY - case 'L': - a_setchesslist(&me); - break; -#endif - } - } - if (me.level >= SYSOP) { - switch (ch) { - case 'N': - a_showname(&me); - me.page = 9999; - break; - } - } - } - free(me.header); - return returnvalue; -} - -int -Announce(void) -{ - setutmpmode(ANNOUNCE); - a_menu(BBSNAME "§G§iÄæ", "man", - ((HasUserPerm(PERM_SYSOP) ) ? SYSOP : NOBODY), - 0, - NULL); - return 0; -} - -#ifdef BLOG -#include <mysql/mysql.h> -void BlogMain(int num) -{ - int oldmode = currutmp->mode; - char genbuf[128], exit = 0; - - // WARNING: n½T»{ currboard/currbid ¤w¥¿½T³]©w¤~¯à¥Î¦¹API¡C - - //setutmpmode(BLOGGING); /* will crash someone using old program */ - sprintf(genbuf, "%sªº³¡¸¨®æ", currboard); - showtitle("³¡¸¨®æ", genbuf); - while( !exit ){ - move(1, 0); - outs("½Ð¿ï¾Ü±zn°õ¦æªº«§@:\n" - "0.¦^¨ì¤W¤@¼h\n" - "1.»s§@³¡¸¨®æ¼ËªO®æ¦¡\n" - " ¨Ï¥Î·sªº config ¥Ø¿ý¤U¼ËªO¸ê®Æ\n" - " ³q±`¦b²Ä¤@¦¸¨Ï¥Î³¡¸¨®æ©Î¼ËªO§ó·sªº®ÉԨϥÎ\n" - "\n" - "2.«·s»s§@³¡¸¨®æ\n" - " ¥u¦b³¡¸¨®æ¸ê®Æ¾ãӶñ¼ªº®ÉÔ¤~¨Ï¥Î\n" - "\n" - "3.±N¥»¤å¥[¤J³¡¸¨®æ\n" - " ±N´å¼Ð©Ò¦b¦ì¸mªº¤å³¹¥[¤J³¡¸¨®æ\n" - "\n" - "4.§R°£°jÅT\n" - "\n" - "5.§R°£¤@½g³¡¸¨®æ\n" - "\n" - "C.«Ø¥ß³¡¸¨®æ¥Ø¿ý (±z¥u¦³²Ä¤@¦¸®É»Ýn)\n" - ); - switch( getans("½Ð¿ï¾Ü(0-5,C)¡H[0]") ){ - case '1': - snprintf(genbuf, sizeof(genbuf), - "bin/builddb.pl -c %s", currboard); - system(genbuf); - break; - case '2': - snprintf(genbuf, sizeof(genbuf), - "bin/builddb.pl -a %s", currboard); - system(genbuf); - break; - case '3': - snprintf(genbuf, sizeof(genbuf), - "bin/builddb.pl -f -n %d %s", num, currboard); - system(genbuf); - break; - case '4':{ - char hash[33]; - int i; - getdata(16, 0, "½Ð¿é¤J¸Ó½gªºÂø´êÈ: ", - hash, sizeof(hash), DOECHO); - for( i = 0 ; hash[i] != 0 ; ++i ) /* «e±¥Î getdata() «OÃÒ¦³ \0 */ - if( !islower(hash[i]) && !isdigit(hash[i]) ) - break; - if( i != 32 ){ - vmsg("¿é¤J¿ù»~"); - break; - } - if( hash[0] != 0 && - getans("½Ð½T©w§R°£(Y/N)?[N] ") == 'y' ){ - MYSQL mysql; - char cmd[256]; - - snprintf(cmd, sizeof(cmd), "delete from comment where " - "hash='%s'&&brdname='%s'", hash, currboard); -#ifdef DEBUG - vmsg(cmd); -#endif - if( !(!mysql_init(&mysql) || - !mysql_real_connect(&mysql, BLOGDB_HOST, BLOGDB_USER, - BLOGDB_PASSWD, BLOGDB_DB, - BLOGDB_PORT, BLOGDB_SOCK, 0) || - mysql_query(&mysql, cmd)) ) - vmsg("¸ê®Æ§R°£§¹¦¨"); - else - vmsg( -#ifdef DEBUG - mysql_error(&mysql) -#else - "database internal error" -#endif - ); - mysql_close(&mysql); - } - } - break; - - case '5': { - char date[9]; - int i; - getdata(16, 0, "½Ð¿é¤J¸Ó½gªº¤é´Á(yyyymmdd): ", - date, sizeof(date), DOECHO); - for( i = 0 ; i < 9 ; ++i ) - if( !isdigit(date[i]) ) - break; - if( i != 8 ){ - vmsg("¿é¤J¿ù»~"); - break; - } - snprintf(genbuf, sizeof(genbuf), - "bin/builddb.pl -D %s %s", date, currboard); - system(genbuf); - } - break; - - case 'C': case 'c': { - fileheader_t item; - char fpath[PATHLEN], adir[PATHLEN], buf[256]; - setapath(fpath, currboard); - stampdir(fpath, &item); - strlcpy(item.title, "¡» Blog", sizeof(item.title)); - strlcpy(item.owner, cuser.userid, sizeof(item.owner)); - - setapath(adir, currboard); - strcat(adir, "/" FN_DIR); - append_record(adir, &item, FHSZ); - - snprintf(buf, sizeof(buf), - "cp -R etc/Blog.Default/" FN_DIR " etc/Blog.Default/* %s/", - fpath); - system(buf); - - more("etc/README.BLOG", YEA); - } - break; - - default: - exit = 1; - break; - } - if( !exit ) - vmsg("³¡¸¨®æ§¹¦¨"); - } - currutmp->mode = oldmode; - pressanykey(); -} -#endif diff --git a/mbbsd/args.c b/mbbsd/args.c deleted file mode 100644 index bbd6be21..00000000 --- a/mbbsd/args.c +++ /dev/null @@ -1,73 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -#ifdef HAVE_SETPROCTITLE - -void -initsetproctitle(int argc, char **argv, char **envp) -{ -} - -#else - - -static char **Argv = NULL; /* pointer to argument vector */ -static int argv_size; /* end of argv */ - -extern char **environ; - -void -initsetproctitle(int argc, char **argv, char **envp) -{ - register int i; - int len=0,nenv=0; - - - /* - * Move the environment so setproctitle can use the space at the top of - * memory. - */ - for (i = 0; envp[i]; i++) - len+=strlen(envp[i])+1; - nenv=i+1; - len+=sizeof(char*)*nenv; - environ = malloc(len); - len=0; - for (i = 0; envp[i]; i++) { - environ[i] = (char*)environ+nenv*sizeof(char*)+len; - strcpy(environ[i], envp[i]); - len+=strlen(envp[i])+1; - } - environ[i] = NULL; - - /* Save start and extent of argv for setproctitle. */ - Argv = argv; - if (i > 0) - argv_size = envp[i - 1] + strlen(envp[i - 1]) - Argv[0]; - else - argv_size = argv[argc - 1] + strlen(argv[argc - 1]) - Argv[0]; -} - -static void -do_setproctitle(const char *cmdline) -{ - int len; - - len = strlen(cmdline) + 1; // +1 for '\0' - if(len > argv_size - 2) // 2 ?? - len = argv_size - 2; - memset(Argv[0], 0, argv_size); - strlcpy(Argv[0], cmdline, len); - Argv[1] = NULL; -} - -void -setproctitle(const char *format,...) -{ - char buf[256]; - va_list args; - va_start(args, format); - vsnprintf(buf, sizeof(buf), format, args); - do_setproctitle(buf); - va_end(args); -} -#endif diff --git a/mbbsd/assess.c b/mbbsd/assess.c deleted file mode 100644 index 4d63a8d8..00000000 --- a/mbbsd/assess.c +++ /dev/null @@ -1,268 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#ifdef ASSESS - -/* do (*num) + n, n is integer. */ -inline static void inc(unsigned char *num, int n) -{ - if (n >= 0 && SALE_MAXVALUE - *num <= n) - (*num) = SALE_MAXVALUE; - else if (n < 0 && *num < -n) - (*num) = 0; - else - (*num) += n; -} - -#define modify_column(_attr) \ -int inc_##_attr(const char *userid, int num) \ -{ \ - userec_t xuser; \ - int uid = getuser(userid, &xuser);\ - if( uid > 0 ){ \ - inc(&xuser._attr, num); \ - passwd_update(uid, &xuser); \ - return xuser._attr; }\ - return 0;\ -} - -modify_column(goodpost); /* inc_goodpost */ -modify_column(badpost); /* inc_badpost */ -modify_column(goodsale); /* inc_goodsale */ -modify_column(badsale); /* inc_badsale */ - -#if 0 //unused function -void set_assess(const char *userid, unsigned char num, int type) -{ - userec_t xuser; - int uid = getuser(userid, &xuser); - if(uid<=0) return; - switch (type){ - case GOODPOST: - xuser.goodpost = num; - break; - case BADPOST: - xuser.badpost = num; - break; - case GOODSALE: - xuser.goodsale = num; - break; - case BADSALE: - xuser.badsale = num; - break; - } - passwd_update(uid, &xuser); -} -#endif - -// how long is AID? see read.c... -#ifndef AIDC_LEN -#define AIDC_LEN (20) -#endif // AIDC_LEN - -// #define MAXGP (100) -#define MAXGP (SALE_MAXVALUE) - -int -u_fixgoodpost(void) -{ - char endinput = 0; - unsigned int newgp = 0; - int bid; - char bname[IDLEN+1]; - char xaidc[AIDC_LEN+1]; - - aidu_t gpaids[MAXGP+1]; - int gpbids[MAXGP+1]; - int cgps = 0; - - clear(); - stand_title("¦Û°ÊÀu¤å×¥¿µ{¦¡"); - - outs("¶}©l×¥¿Àu¤å¤§«e¡A¦³¨Ç¥\\½Òn³Â·Ð±z¥ý¬d¦n¡G\n\n" - "½Ð¥ý§ä¨ì§A©Ò¦³ªºÀu¤å¤å³¹ªº¬ÝªO»P" AID_DISPLAYNAME "\n" - AID_DISPLAYNAME "ªº¬d¸ß¤èªk¬O¦b¸Ó½g¤å³¹«e±«ö¤U¤j¼g Q ¡C\n" - "¬d¦n«á½Ð§â³o¨Ç¸ê®Æ©ñ¦b¤âÃä¡Aµ¥¤U·|½Ð±z¿é¤J¡C\n" - "¥t¥~¡AY¦³¦h«µn¤J½Ð¥ýÃö³¬¨ä¥¦³s½u¡C\n" - "\n"); - outs("¦pªG¤@¤Á³£·Ç³Æ¦n¤F¡A½Ð«ö¤U y ¶}©l¡A©Î¨ä¥¦¥ô·NÁä¸õ¥X¡C\n\n"); - if (getans("Àu¤åªº¸ê®Æ³£¬d¦n¤F¶Ü¡H") != 'y') - { - vmsg("¸õ¥X×¥¿µ{¦¡¡C"); - return 0; - } - while (!endinput && newgp < MAXGP) - { - int y, x = 0; - boardheader_t *bh = NULL; - - move(1, 0); clrtobot(); - outs("½Ð¨Ì§Ç¿é¤JÀu¤å¸ê°T¡A¥þ³¡§¹¦¨«á«ö ENTER §Y¥i°±¤î¡C\n"); - - move(b_lines-2, 0); clrtobot(); - prints("¥Ø«e¤w½T»{Àu¤å¼Æ¥Ø: %d" ANSI_RESET "\n\n", newgp); - - if (!getdata(5, 0, "½Ð¿é¤JÀu¤å¤å³¹©Ò¦b¬ÝªO¦WºÙ: ", - bname, sizeof(bname), DOECHO)) - { - move(5, 0); - if (getans(ANSI_COLOR(1;33)"½T©w¥þ³¡¿é¤J§¹¦¨¤F¶Ü¡H " - ANSI_RESET "[y/N]: ") != 'y') - continue; - endinput = 1; break; - } - move (6, 0); - outs("½T»{¬ÝªO... "); - if (bname[0] == '\0' || !(bid = getbnum(bname))) - { - outs(ANSI_COLOR(1;31) "¬ÝªO¤£¦s¦b¡I"); - vmsg("½Ð«·s¿é¤J¡C"); - continue; - } - assert(0<=bid-1 && bid-1<MAX_BOARD); - bh = getbcache(bid); - strlcpy(bname, bh->brdname, sizeof(bname)); - prints("¤w§ä¨ì¬ÝªO --> %s\n", bname); - getyx(&y, &x); - - // loop AID query - while (newgp < MAXGP) - { - int n; - int fd; - char dirfile[PATHLEN]; - char *sp; - aidu_t aidu = 0; - fileheader_t fh; - - move(y, 0); clrtobot(); - move(b_lines-2, 0); clrtobot(); - prints("¥Ø«e¤w½T»{Àu¤å¼Æ¥Ø: %d" ANSI_RESET "\n\n", newgp); - - if (getdata(y, 0, "½Ð¿é¤J" AID_DISPLAYNAME ": #", - xaidc, AIDC_LEN, DOECHO) == 0) - break; - - sp = xaidc; - while(*sp == ' ') sp ++; - if(*sp == '#') sp ++; - - if((aidu = aidc2aidu(sp)) <= 0) - { - outs(ANSI_COLOR(1;31) AID_DISPLAYNAME "®æ¦¡¤£¥¿½T¡I"); - vmsg("½Ð«·s¿é¤J¡C"); - continue; - } - - // check repeated input of same board+AID. - for (n = 0; n < cgps; n++) - { - if (gpaids[n] == aidu && gpbids[n] == bid) - { - vmsg("±z¤w¿é¤J¹L¦¹Àu¤å¤F¡A½Ð«·s¿é¤J¡C"); - aidu = 0; - break; - } - } - - if (aidu <= 0) - continue; - - // find aidu in board - n = -1; - // see read.c, search .bottom first. - if (n < 0) - { - outs("·j´M¸m©³¤å³¹..."); - setbfile(dirfile, bname, FN_DIR ".bottom"); - n = search_aidu(dirfile, aidu); - } - if (n < 0) { - // search board - outs("¥¼§ä¨ì¡C\n·j´M¬ÝªO¤å³¹.."); - setbfile(dirfile, bname, FN_DIR); - n = search_aidu(dirfile, aidu); - } - if (n < 0) - { - // search digest - outs("¥¼§ä¨ì¡C\n·j´M¤åºK.."); - setbfile(dirfile, currboard, fn_mandex); - n = search_aidu(dirfile, aidu); - } - if (n < 0) - { - // search failed... - outs("¥¼§ä¨ì\n" ANSI_COLOR(1;31) "§ä¤£¨ì¤å³¹¡I"); - vmsg("½Ð½T»{«á«·s¿é¤J¡C"); - continue; - } - - // found something - fd = open(dirfile, O_RDONLY); - if (fd < 0) - { - outs(ANSI_COLOR(1;31) "¨t²Î¿ù»~¡C ½ÐµyÔ¦A«¸Õ¡C\n"); - vmsg("Y«ùÄòµo¥Í½Ð¦Ü" GLOBAL_BUGREPORT "³ø§i¡C"); - continue; - } - - lseek(fd, n*sizeof(fileheader_t), SEEK_SET); - memset(&fh, 0, sizeof(fh)); - read(fd, &fh, sizeof(fh)); - outs("\n¶}©l®Ö¹ï¸ê®Æ...\n"); - n = 1; - if (strcmp(fh.owner, cuser.userid) != 0) - n = 0; - prints("§@ªÌ: %s (%s)\n", fh.owner, n ? "¥¿½T" : - ANSI_COLOR(1;31) "¿ù»~" ANSI_RESET); - if (!(fh.filemode & FILE_MARKED)) - n = 0; - prints("¢Û¤å: %s\n", (fh.filemode & FILE_MARKED) ? "¥¿½T" : - ANSI_COLOR(1;31) "¿ù»~" ANSI_RESET); - prints("±ÀÂË: %d\n", fh.recommend); - close(fd); - if (!n) - { - vmsg("¿é¤Jªº¤å³¹¨Ã«DÀu¤å¡A½Ð«·s¿é¤J¡C"); - continue; - } - n = fh.recommend / 10; - prints("pºâÀu¤å¼ÆÈ: %+d\n", n); - - if (n > 0) - { - // log new data - newgp += n; - gpaids[cgps] = aidu; - gpbids[cgps] = bid; - cgps ++; - } - - clrtobot(); - - - vmsg("Àu¤å¤w½T»{¡CYn¿é¤J¨ä¥¦¬ÝªO¤å³¹½Ð¦bAIDÄæªÅ¥Õ«ö ENTER"); - } - vmsgf("%s ¬ÝªO¿é¤J§¹¦¨¡C", bname); - } - if (newgp > MAXGP) - newgp = MAXGP; - if (newgp <= cuser.goodpost) - { - vmsg("½T»{Àu¤å¼Æ¥Ø¥¼°ª©ó¤w¦³Àu¤å¼Æ¡A¤£½Õ¾ã¡C"); - } else { - log_filef("log/fixgoodpost.log", LOG_CREAT, - "%s %s ¦Û°Ê×¥¿Àu¤å¼Æ: ¥Ñ %d Åܬ° %d\n", Cdate(&now), cuser.userid, - cuser.goodpost, newgp); - cuser.goodpost = newgp; - // update passwd file here? - passwd_force_update(ALERT_PWD_GOODPOST); - passwd_update(usernum, &cuser); - vmsgf("§ó·sÀu¤å¼Æ¥Ø¬°%d¡C", newgp); - } - - return 0; -} - -#endif diff --git a/mbbsd/bbs.c b/mbbsd/bbs.c deleted file mode 100644 index 83cdb5c0..00000000 --- a/mbbsd/bbs.c +++ /dev/null @@ -1,3986 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#ifdef EDITPOST_SMARTMERGE - -#include "fnv_hash.h" -#define SMHASHLEN (64/8) - -#endif // EDITPOST_SMARTMERGE - -#define WHEREAMI_LEVEL 16 - -static int recommend(int ent, fileheader_t * fhdr, const char *direct); -static int do_add_recommend(const char *direct, fileheader_t *fhdr, - int ent, const char *buf, int type); -static int view_postinfo(int ent, const fileheader_t * fhdr, const char *direct, int crs_ln); - -#ifdef ASSESS -static char * const badpost_reason[] = { - "¼s§i", "¤£·í¥ÎÃã", "¤H¨§ðÀ»" -}; -#endif - -/* TODO multi.money is a mess. - * please help verify and finish these. - */ -/* modes to invalid multi.money */ -#define INVALIDMONEY_MODES (FILE_ANONYMOUS | FILE_BOTTOM | FILE_DIGEST | FILE_BID) - -/* query money by fileheader pointer. - * return <0 if money is not valid. - */ -int -query_file_money(const fileheader_t *pfh) -{ - fileheader_t hdr; - - if( (currmode & MODE_SELECT) && - (pfh->multi.refer.flag) && - (pfh->multi.refer.ref > 0)) // really? not sure, copied from other's code - { - char genbuf[MAXPATHLEN]; - - /* it is assumed that in MODE_SELECT, currboard is selected. */ - setbfile(genbuf, currboard, FN_DIR); - get_record(genbuf, &hdr, sizeof(hdr), pfh->multi.refer.ref); - pfh = &hdr; - } - - if(pfh->filemode & INVALIDMONEY_MODES || pfh->multi.money > MAX_POST_MONEY) - return -1; - - return pfh->multi.money; -} - -// lite weight version to update dir files -static int -modify_dir_lite( - const char *direct, int ent, const char *fhdr_name, - time4_t modified, const char *title, char recommend) -{ - // since we want to do 'modification'... - int fd; - off_t sz = dashs(direct); - fileheader_t fhdr; - - // TODO lock? - // PttLock(fd, offset, size, F_WRLCK); - // write(fd, rptr, size); - // PttLock(fd, offset, size, F_UNLCK); - - // prevent black holes - if (sz < sizeof(fileheader_t) * (ent) || - (fd = open(direct, O_RDWR)) < 0 ) - return -1; - - // also check if fhdr->filename is same. - // let sz = base offset - sz = (sizeof(fileheader_t) * (ent-1)); - if (lseek(fd, sz, SEEK_SET) < 0 || - read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr) || - strcmp(fhdr.filename, fhdr_name) != 0) - { - close(fd); - return -1; - } - - // update records - if (modified > 0) - fhdr.modified = modified; - - if (title && *title) - strcpy(fhdr.title, title); - - if (recommend) - { - recommend += fhdr.recommend; - if (recommend > MAX_RECOMMENDS) recommend = MAX_RECOMMENDS; - else if (recommend < -MAX_RECOMMENDS) recommend = -MAX_RECOMMENDS; - fhdr.recommend = recommend; - } - - if (lseek(fd, sz, SEEK_SET) >= 0) - write(fd, &fhdr, sizeof(fhdr)); - - close(fd); - - return 0; -} - -static void -check_locked(fileheader_t *fhdr) -{ - boardheader_t *bp = NULL; - - if (currstat == RMAIL) - return; - if (!currboard[0] || currbid <= 0) - return; - bp = getbcache(currbid); - if (!bp) - return; - if (!(fhdr->filemode & FILE_SOLVED)) - return; - if (!(fhdr->filemode & FILE_MARKED)) - return; - syncnow(); - bp->SRexpire = now; -} - -/* hack for listing modes */ -enum LISTMODES { - LISTMODE_DATE = 0, - LISTMODE_MONEY, -}; -static char *listmode_desc[] = { - "¤é ´Á", - "»ù ®æ", -}; -static int currlistmode = LISTMODE_DATE; - -#define IS_LISTING_MONEY \ - (currlistmode == LISTMODE_MONEY || \ - ((currmode & MODE_SELECT) && (currsrmode & RS_MONEY))) - -void -anticrosspost(void) -{ - log_filef("etc/illegal_money", LOG_CREAT, - ANSI_COLOR(1;33;46) "%s " - ANSI_COLOR(37;45) "cross post ¤å³¹ " - ANSI_COLOR(37) " %s" ANSI_RESET "\n", - cuser.userid, ctime4(&now)); - post_violatelaw(cuser.userid, BBSMNAME "¨t²Îĵ¹î", - "Cross-post", "»@³æ³B¥÷"); - cuser.userlevel |= PERM_VIOLATELAW; - cuser.timeviolatelaw = now; - cuser.vl_count++; - mail_id(cuser.userid, "Cross-Post»@³æ", - "etc/crosspost.txt", BBSMNAME "ĵ¹î³¡¶¤"); - if ((now - cuser.firstlogin) / 86400 < 14) - delete_allpost(cuser.userid); - kick_all(cuser.userid); // XXX: in2: wait for testing - u_exit("Cross Post"); - exit(0); -} - -/* Heat CharlieL */ -int -save_violatelaw(void) -{ - char buf[128], ok[3]; - int day; - - setutmpmode(VIOLATELAW); - clear(); - stand_title("ú»@³æ¤¤¤ß"); - - if (!(cuser.userlevel & PERM_VIOLATELAW)) { - vmsg("§A¨S¦³³Q¶}»@³æ~~"); - return 0; - } - - day = cuser.vl_count*3 - (now - cuser.timeviolatelaw)/86400; - if (day > 0) { - vmsgf("¨Ì·Ó¹H³W¦¸¼Æ, §AÁÙ»Ýn¤Ï¬Ù %d ¤Ñ¤~¯àú»@³æ", day); - return 0; - } - reload_money(); - if (cuser.money < (int)cuser.vl_count * 1000) { - snprintf(buf, sizeof(buf), - ANSI_COLOR(1;31) "³o¬O§A²Ä %d ¦¸¹H¤Ï¥»¯¸ªk³W" - "¥²¶·Ãº¥X %d $Ptt ,§A¥u¦³ %d ¤¸, ¿ú¤£°÷°Õ!!" ANSI_RESET, - (int)cuser.vl_count, (int)cuser.vl_count * 1000, cuser.money); - mouts(22, 0, buf); - pressanykey(); - return 0; - } - move(5, 0); - prints("³o¬O§A²Ä %d ¦¸¹Hªk ¥²¶·Ãº¥X %d $Ptt\n\n", - cuser.vl_count, cuser.vl_count * 1000); - outs(ANSI_COLOR(1;37) "§Aª¾¹D¶Ü? ¦]¬°§Aªº¹Hªk " - "¤w¸g³y¦¨«Ü¦h¤Hªº¤£«K" ANSI_RESET "\n"); - outs(ANSI_COLOR(1;37) "§A¬O§_½T©w¥H«á¤£·|¦A¥Ç¤F¡H" ANSI_RESET "\n"); - - if (!getdata(10, 0, "½T©w¶Ü¡H[y/N]:", ok, sizeof(ok), LCECHO) || - ok[0] != 'y') - { - move(15, 0); - outs( ANSI_COLOR(1;31) "¤£·Q¥I¿ú¶Ü¡H ÁÙ¬O¤£ª¾¹Dn«ö y ¡H\n" - "½Ð¾i¦¨¬Ý²M·¡¨t²Î°T®§ªº¦n²ßºD¡C\n" - "µ¥§A·Q³q¤F¦A¨Ó§a!! §Ú¬Û«H§A¤£·|ª¾¿ù¤£§ïªº~~~" ANSI_RESET); - pressanykey(); - return 0; - } - - //Ptt:check one more time - reload_money(); - if (cuser.money < (int)cuser.vl_count * 1000) - { - log_filef("log/violation", LOG_CREAT, - "%24.24s %s pay-violation error: race-conditionn hack?\n", - ctime4(&now), cuser.userid); - vmsg("¿ú«ç»ò©¿µM¤£°÷¤F¡H ¸Õ¹Ï´ÛÄF¨t²Î³Q¬d¨ì±N¬å±b¸¹¡I"); - return 0; - } - - demoney(-1000 * cuser.vl_count); - cuser.userlevel &= (~PERM_VIOLATELAW); - // force overriding alerts - if(currutmp) - currutmp->alerts &= ~ALERT_PWD_PERM; - passwd_update(usernum, &cuser); - sendalert(cuser.userid, ALERT_PWD_PERM); - log_filef("log/violation", LOG_CREAT, - "%24.24s %s pay-violation: $%d complete.\n", - ctime4(&now), cuser.userid, (int)cuser.vl_count*1000); - - vmsg("»@³æ¤w¥I¡A½ÐºÉ³t«·sµn¤J¡C"); - return 0; -} - -/* - * void make_blist() { CreateNameList(); apply_boards(g_board_names); } - */ - -static time4_t *board_note_time = NULL; - -void -set_board(void) -{ - boardheader_t *bp; - - bp = getbcache(currbid); - if( !HasBoardPerm(bp) ){ - vmsg("access control violation, exit"); - u_exit("access control violation!"); - exit(-1); - } - - if( HasUserPerm(PERM_SYSOP) && - (bp->brdattr & BRD_HIDE) && - !is_BM_cache(bp - bcache + 1) && - !is_hidden_board_friend((int)(bp - bcache) + 1, currutmp->uid) ) - vmsg("¶i¤J¥¼¸g±ÂÅv¬ÝªO"); - - board_note_time = &bp->bupdate; - - if(bp->BM[0] <= ' ') - strcpy(currBM, "¼x¨D¤¤"); - else - { - /* calculate with other title information */ - int l = 0; - - snprintf(currBM, sizeof(currBM), "ªO¥D:%s", bp->BM); - /* title has +7 leading symbols */ - l += strlen(bp->title); - if(l >= 7) - l -= 7; - else - l = 0; - l += 8 + strlen(currboard); /* trailing stuff */ - l += strlen(bp->brdname); - l = t_columns - l -strlen(currBM); - -#ifdef _DEBUG - { - char buf[MAXPATHLEN]; - sprintf(buf, "title=%d, brdname=%d, currBM=%d, t_c=%d, l=%d", - strlen(bp->title), strlen(bp->brdname), - strlen(currBM), t_columns, l); - vmsg(buf); - } -#endif - - if(l < 0 && ((l += strlen(currBM)) > 7)) - { - currBM[l] = 0; - currBM[l-1] = currBM[l-2] = '.'; - } - } - - /* init basic perm, but post perm is checked on demand */ - currmode = (currmode & (MODE_DIRTY | MODE_GROUPOP)) | MODE_STARTED; - if (!HasUserPerm(PERM_NOCITIZEN) && - (HasUserPerm(PERM_ALLBOARD) || is_BM_cache(currbid))) { - currmode = currmode | MODE_BOARD | MODE_POST | MODE_POSTCHECKED; - } -} - -int IsFreeBoardName(const char *brdname) -{ - if (strcmp(currboard, GLOBAL_TEST) == 0) - return 1; - if (strcmp(currboard, ALLPOST) == 0) - return 1; - return 0; -} - -/* check post perm on demand, no double checks in current board - * currboard MUST be defined! - * XXX can we replace currboard with currbid ? */ -int -CheckPostPerm(void) -{ - static time4_t last_chk_time = 0x0BAD0BB5; /* any magic number */ - static int last_board_index = 0; /* for speed up */ - int valid_index = 0; - boardheader_t *bp = NULL; - - if (currmode & MODE_DIGEST) - return 0; - - if (currmode & MODE_POSTCHECKED) - { - /* checked? let's check if perm reloaded */ - if (last_board_index < 1 || last_board_index > SHM->Bnumber) - { - /* invalid board index, refetch. */ - last_board_index = getbnum(currboard); - valid_index = 1; - } - assert(0<=last_board_index-1 && last_board_index-1<MAX_BOARD); - bp = getbcache(last_board_index); - - if(bp->perm_reload != last_chk_time) - currmode &= ~MODE_POSTCHECKED; - } - - if (!(currmode & MODE_POSTCHECKED)) - { - if(!valid_index) - { - last_board_index = getbnum(currboard); - bp = getbcache(last_board_index); - } - last_chk_time = bp->perm_reload; - currmode |= MODE_POSTCHECKED; - - // vmsg("reload board postperm"); - - if (haspostperm(currboard)) { - currmode |= MODE_POST; - return 1; - } - currmode &= ~MODE_POST; - return 0; - } - return (currmode & MODE_POST); -} - -int CheckPostRestriction(int bid) -{ - boardheader_t *bp; - if ((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP)) - return 1; - assert(0<=bid-1 && bid-1<MAX_BOARD); - bp = getbcache(bid); - - // check first-login - if (cuser.firstlogin > (now - (time4_t)bp->post_limit_regtime * 2592000)) - return 0; - if (cuser.numlogins / 10 < (unsigned int)bp->post_limit_logins) - return 0; - if (cuser.numposts / 10 < (unsigned int)bp->post_limit_posts) - return 0; - if (cuser.badpost > (255 - (unsigned int)bp->post_limit_badpost)) - return 0; - - return 1; -} - -static void -readtitle(void) -{ - boardheader_t *bp; - char *brd_title; - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - if(bp->bvote != 2 && bp->bvote) - brd_title = "¥»¬ÝªO¶i¦æ§ë²¼¤¤"; - else - brd_title = bp->title + 7; - - showtitle(currBM, brd_title); - outs("[¡ö]Â÷¶} [¡÷]¾\\Ū [^P]µoªí¤å³¹ [b]³Æ§Ñ¿ý [d]§R°£ [z]ºëµØ°Ï [TAB]¤åºK [h]»¡©ú\n"); - prints(ANSI_COLOR(7) " ½s¸¹ %s §@ ªÌ ¤å ³¹ ¼Ð ÃD", - IS_LISTING_MONEY ? listmode_desc[LISTMODE_MONEY] : listmode_desc[currlistmode]); - -#ifdef USE_COOLDOWN - if ( bp->brdattr & BRD_COOLDOWN && - !((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP))) - outslr("", 44, ANSI_RESET, 0); - else -#endif - { - char buf[32]; - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - sprintf(buf, "¤H®ð:%d ", - SHM->bcache[currbid - 1].nuser); - outslr("", 44, buf, -1); - outs(ANSI_RESET); - } -} - -static void -readdoent(int num, fileheader_t * ent) -{ - int type = ' '; - char *mark, *title, - color, special = 0, isonline = 0, recom[8]; - char *typeattr = ""; - char isunread = 0, oisunread = 0; - - oisunread = isunread = - brc_unread(currbid, ent->filename, ent->modified); - - // modified tag - if (isunread == 2) - { - // ignore unread, if user doesn't want to show it. - if (cuser.uflag & NO_MODMARK_FLAG) - { - oisunread = isunread = 0; - } - // if user wants colored marks, use 'read' marks - else if (cuser.uflag & COLORED_MODMARK) - { - isunread = 0; - typeattr = ANSI_COLOR(36); - } - } - - type = isunread ? '+' : ' '; - if (isunread == 2) type = '~'; - - // handle 'type" - if ((currmode & MODE_BOARD) && (ent->filemode & FILE_DIGEST)) - type = (type == ' ') ? '*' : '#'; - else if (currmode & MODE_BOARD || HasUserPerm(PERM_LOGINOK)) - { - if (ent->filemode & FILE_MARKED) - { - if(ent->filemode & FILE_SOLVED) - type = '!'; - else if (isunread == 0) - type = 'm'; - else if (isunread == 1) - type = 'M'; - else if (isunread == 2) - type = '='; - } else if (TagNum && !Tagger(atoi(ent->filename + 2), 0, TAG_NIN)) - type = 'D'; - else if (ent->filemode & FILE_SOLVED) - type = (type == ' ') ? 's': 'S'; - } - - // the only special case: ' ' with isunread == 2, - // change to '+' with gray attribute. - if (type == ' ' && oisunread == 2) - { - typeattr = ANSI_COLOR(1;30); - type = '+'; - } - - title = ent->filename[0]!='L' ? subject(ent->title) : "<¥»¤åÂê©w>"; - if (ent->filemode & FILE_VOTE) - color = '2', mark = "£¾"; - else if (ent->filemode & FILE_BID) - color = '6', mark = "¢C"; - else if (title == ent->title) - color = '1', mark = "¡¼"; - else - color = '3', mark = "R:"; - - /* §â¹Lªøªº title ¬å±¼¡C «e±¬ù¦³ 33 Ó¦r¤¸¡C */ - { - int l = t_columns - 34; /* 33+1, for trailing one more space */ - unsigned char *p = (unsigned char*)title; - - /* strlen ¶¶«K°µ safe print checking */ - while (*p && l > 0) - { - /* ¥»¨ÓÀ³¸Ó°µ DBCS checking, Ãi±o¼g¤F */ - if(*p < ' ') - *p = ' '; - p++, l--; - } - - if (*p && l <= 0) - strcpy((char*)p-3, " ¡K"); - } - - if (!strncmp(title, "[¤½§i]", 6)) - special = 1; - - isonline = query_online(ent->owner); - - if(ent->recommend >= MAX_RECOMMENDS) - strcpy(recom,"1mÃz"); - else if(ent->recommend>9) - sprintf(recom,"3m%2d",ent->recommend); - else if(ent->recommend>0) - sprintf(recom,"2m%2d",ent->recommend); - else if(ent->recommend <= -MAX_RECOMMENDS) - sprintf(recom,"0mXX"); - else if(ent->recommend<-10) - sprintf(recom,"0mX%d",-ent->recommend); - else strcpy(recom,"0m "); - - /* start printing */ - if (ent->filemode & FILE_BOTTOM) - outs(" " ANSI_COLOR(1;33) " ¡¹ " ANSI_RESET); - else - /* recently we found that many boards have >10k articles, - * so it's better to use 5+2 (2 for cursor marker) here. - * XXX if we are in big term, enlarge here. - */ - prints("%7d", num); - - prints(" %s%c" ESC_STR "[0;1;3%4.4s" ANSI_RESET, - typeattr, type, recom); - - if(IS_LISTING_MONEY) - { - int m = query_file_money(ent); - if(m < 0) - outs(" ---- "); - else - prints("%5d ", m); - } - else // LISTMODE_DATE - { -#ifdef COLORDATE - prints(ANSI_COLOR(%d) "%-6.5s" ANSI_RESET, - (ent->date[3] + ent->date[4]) % 7 + 31, ent->date); -#else - prints("%-6.5s", ent->date); -#endif - } - - // print author - if(isonline) outs(ANSI_COLOR(1)); - prints("%-13.12s", ent->owner); - if(isonline) outs(ANSI_RESET); - - if (strncmp(currtitle, title, TTLEN)) - prints("%s " ANSI_COLOR(1) "%.*s" ANSI_RESET "%s\n", - mark, special ? 6 : 0, title, special ? title + 6 : title); - else - prints(ANSI_COLOR(1;3%c) "%s %s" ANSI_RESET "\n", - color, mark, title); -} - -int -whereami(void) -{ - boardheader_t *bh, *p[WHEREAMI_LEVEL]; - int i, j; - int bid = currbid; - - if (!bid) - return 0; - - move(1, 0); - clrtobot(); - assert(0<=bid-1 && bid-1<MAX_BOARD); - bh = getbcache(bid); - p[0] = bh; - for (i = 0; i+1 < WHEREAMI_LEVEL && p[i]->parent>1 && p[i]->parent < numboards; i++) - p[i + 1] = getbcache(p[i]->parent); - j = i; - prints("§Ú¦bþ?\n%-40.40s %.13s\n", p[j]->title + 7, p[j]->BM); - for (j--; j >= 0; j--) - prints("%*s %-13.13s %-37.37s %.13s\n", (i - j) * 2, "", - p[j]->brdname, p[j]->title, - p[j]->BM); - - pressanykey(); - return FULLUPDATE; -} - - -static int -do_select(void) -{ - char bname[20]; - - setutmpmode(SELECT); - move(0, 0); - clrtoeol(); - CompleteBoard(MSG_SELECT_BOARD, bname); - - if(enter_board(bname) < 0) - return FULLUPDATE; - - move(1, 0); - clrtoeol(); - return NEWDIRECT; -} - -/* ----------------------------------------------------- */ -/* §ï¨} innbbsd Âà¥X«H¥ó¡B³s½u¬å«H¤§³B²zµ{§Ç */ -/* ----------------------------------------------------- */ -void -outgo_post(const fileheader_t *fh, const char *board, const char *userid, const char *nickname) -{ - FILE *foo; - - if ((foo = fopen("innd/out.bntp", "a"))) { - fprintf(foo, "%s\t%s\t%s\t%s\t%s\n", - board, fh->filename, userid, nickname, fh->title); - fclose(foo); - } -} - -static void -cancelpost(const fileheader_t *fh, int by_BM, char *newpath) -{ - FILE *fin, *fout; - char *ptr, *brd; - fileheader_t postfile; - char genbuf[200]; - char nick[STRLEN], fn1[MAXPATHLEN]; - int len = 42-strlen(currboard); - struct tm *ptime = localtime4(&now); - - if(!fh->filename[0]) return; - setbfile(fn1, currboard, fh->filename); - if ((fin = fopen(fn1, "r"))) { - brd = by_BM ? "deleted" : "junk"; - - memcpy(&postfile, fh, sizeof(fileheader_t)); - setbpath(newpath, brd); - stampfile_u(newpath, &postfile); - - nick[0] = '\0'; - while (fgets(genbuf, sizeof(genbuf), fin)) { - if (!strncmp(genbuf, str_author1, LEN_AUTHOR1) || - !strncmp(genbuf, str_author2, LEN_AUTHOR2)) { - if ((ptr = strrchr(genbuf, ')'))) - *ptr = '\0'; - if ((ptr = (char *)strchr(genbuf, '('))) - strlcpy(nick, ptr + 1, sizeof(nick)); - break; - } - } - if(!strncasecmp(postfile.title, str_reply, 3)) - len=len+4; - sprintf(postfile.title, "%-*.*s.%sªO", len, len, fh->title, currboard); - - if ((fout = fopen("innd/cancel.bntp", "a"))) { - fprintf(fout, "%s\t%s\t%s\t%s\t%s\n", currboard, fh->filename, - cuser.userid, nick, fh->title); - fclose(fout); - } - fclose(fin); - log_filef(fn1, LOG_CREAT, "\n¡° Deleted by: %s (%s) %d/%d", - cuser.userid, fromhost, ptime->tm_mon + 1, ptime->tm_mday); - Rename(fn1, newpath); - setbdir(genbuf, brd); - append_record(genbuf, &postfile, sizeof(postfile)); - setbtotal(getbnum(brd)); - } -} - -static void -do_deleteCrossPost(const fileheader_t *fh, char bname[]) -{ - char bdir[MAXPATHLEN]="", file[MAXPATHLEN]=""; - fileheader_t newfh; - if(!bname || !fh) return; - - int i, bid = getbnum(bname); - if(bid <=0 || !fh->filename[0]) return; - - boardheader_t *bp = getbcache(bid); - if(!bp) return; - - setbdir(bdir, bname); - setbfile(file, bname, fh->filename); - memcpy(&newfh, fh, sizeof(fileheader_t)); - // Ptt: protect original fh - // because getindex safe_article_delete will change fh in some case - if( (i=getindex(bdir, &newfh, 0))>0) - { -#ifdef SAFE_ARTICLE_DELETE - if(bp && !(currmode & MODE_DIGEST) && bp->nuser > 30 ) - safe_article_delete(i, &newfh, bdir); - else -#endif - delete_record(bdir, sizeof(fileheader_t), i); - setbtotal(bid); - unlink(file); - } -} - -static void -deleteCrossPost(const fileheader_t *fh, char *bname) -{ - if(!fh || !fh->filename[0]) return; - - if(!strcmp(bname, ALLPOST) || !strcmp(bname, "NEWIDPOST") || - !strcmp(bname, ALLHIDPOST) || !strcmp(bname, "UnAnonymous")) - { - int len=0; - char xbname[TTLEN + 1], *po = strrchr(fh->title, '.'); - if(!po) return; - po++; - len = (int) strlen(po)-2; - - if(len > TTLEN) return; - sprintf(xbname, "%.*s", len, po); - do_deleteCrossPost(fh, xbname); - } - else - { - do_deleteCrossPost(fh, ALLPOST); - } -} - -void -delete_allpost(const char *userid) -{ - fileheader_t fhdr; - int fd, i; - char bdir[MAXPATHLEN]="", file[MAXPATHLEN]=""; - - if(!userid) return; - - setbdir(bdir, ALLPOST); - if( (fd = open(bdir, O_RDWR)) != -1) - { - for(i=0; read(fd, &fhdr, sizeof(fileheader_t)) >0; i++){ - if(strcmp(fhdr.owner, userid)) - continue; - deleteCrossPost(&fhdr, ALLPOST); - setbfile(file, ALLPOST, fhdr.filename); - unlink(file); - - sprintf(fhdr.title, "(¥»¤å¤w³Q§R°£)"); - strcpy(fhdr.filename, ".deleted"); - strcpy(fhdr.owner, "-"); - lseek(fd, sizeof(fileheader_t) * i, SEEK_SET); - write(fd, &fhdr, sizeof(fileheader_t)); - } - close(fd); - } -} - -/* ----------------------------------------------------- */ -/* µoªí¡B¦^À³¡B½s¿è¡BÂà¿ý¤å³¹ */ -/* ----------------------------------------------------- */ -static int -solveEdFlagByBoard(const char *bn, int flags) -{ - if ( -#ifdef GLOBAL_BBSMOVIE - strcmp(bn, GLOBAL_BBSMOVIE) == 0 || -#endif -#ifdef GLOBAL_TEST - strcmp(bn, GLOBAL_TEST) == 0 || -#endif - 0 - ) - { - flags |= EDITFLAG_UPLOAD | EDITFLAG_ALLOWLARGE; - } - return flags; -} - -void -do_reply_title(int row, const char *title) -{ - char genbuf[200]; - char genbuf2[4]; - char tmp_title[STRLEN]; - - if (strncasecmp(title, str_reply, 4)) - snprintf(tmp_title, sizeof(tmp_title), "Re: %s", title); - else - strlcpy(tmp_title, title, sizeof(tmp_title)); - tmp_title[TTLEN - 1] = '\0'; - snprintf(genbuf, sizeof(genbuf), "±Ä¥Îì¼ÐÃD¡m%.60s¡n¶Ü?[Y] ", tmp_title); - getdata(row, 0, genbuf, genbuf2, 4, LCECHO); - if (genbuf2[0] == 'n' || genbuf2[0] == 'N') - getdata(++row, 0, "¼ÐÃD¡G", tmp_title, TTLEN, DOECHO); - // don't getdata() on non-local variable save_title directly, to avoid reentrant crash. - strlcpy(save_title, tmp_title, sizeof(save_title)); -} - -void -do_crosspost(const char *brd, fileheader_t *postfile, const char *fpath, - int isstamp) -{ - char genbuf[200]; - int len = 42-strlen(currboard); - fileheader_t fh; - int bid = getbnum(brd); - - if(bid <= 0 || bid > MAX_BOARD) return; - - if(!strncasecmp(postfile->title, str_reply, 3)) - len=len+4; - - memcpy(&fh, postfile, sizeof(fileheader_t)); - if(isstamp) - { - setbpath(genbuf, brd); - stampfile(genbuf, &fh); - } - else - setbfile(genbuf, brd, postfile->filename); - - if(!strcmp(brd, "UnAnonymous")) - strcpy(fh.owner, cuser.userid); - - sprintf(fh.title,"%-*.*s.%sªO", len, len, postfile->title, currboard); - unlink(genbuf); - Copy((char *)fpath, genbuf); - postfile->filemode = FILE_LOCAL; - setbdir(genbuf, brd); - if (append_record(genbuf, &fh, sizeof(fileheader_t)) != -1) { - SHM->lastposttime[bid - 1] = now; - touchbpostnum(bid, 1); - } -} -static void -setupbidinfo(bid_t *bidinfo) -{ - char buf[PATHLEN]; - bidinfo->enddate = gettime(20, now+86400,"µ²§ô¼Ð®×©ó"); - do{ - getdata_str(21, 0, "©³»ù:", buf, 8, LCECHO, "1"); - } while( (bidinfo->high = atoi(buf)) <= 0 ); - do{ - getdata_str(21, 20, "¨C¼Ð¦Ü¤Ö¼W¥[¦h¤Ö:", buf, 5, LCECHO, "1"); - } while( (bidinfo->increment = atoi(buf)) <= 0 ); - getdata(21,44, "ª½±µÁʶR»ù(¥i¤£³]):",buf, 10, LCECHO); - bidinfo->buyitnow = atoi(buf); - - getdata_str(22,0, - "¥I´Ú¤è¦¡: 1." MONEYNAME "¹ô 2.¶l§½©Î»È¦æÂà±b" - "3.¤ä²¼©Î¹q¶× 4.¶l§½³f¨ì¥I´Ú [1]:", - buf, 3, LCECHO,"1"); - bidinfo->payby = (buf[0] - '1'); - if( bidinfo->payby < 0 || bidinfo->payby > 3) - bidinfo->payby = 0; - getdata_str(23, 0, "¹B¶O(0:§K¹B¶O©Î¤å¤¤»¡©ú)[0]:", buf, 6, LCECHO, "0"); - bidinfo->shipping = atoi(buf); - if( bidinfo->shipping < 0 ) - bidinfo->shipping = 0; -} -static void -print_bidinfo(FILE *io, bid_t bidinfo) -{ - char *payby[4]={MONEYNAME "¹ô", "¶l§½©Î»È¦æÂà±b", - "¤ä²¼©Î¹q¶×", "¶l§½³f¨ì¥I´Ú"}; - if(io){ - if( !bidinfo.userid[0] ) - fprintf(io, "°_¼Ð»ù: %-20d\n", bidinfo.high); - else - fprintf(io, "¥Ø«e³Ì°ª»ù:%-20d¥X»ùªÌ:%-16s\n", - bidinfo.high, bidinfo.userid); - fprintf(io, "¥I´Ú¤è¦¡: %-20sµ²§ô©ó:%-16s\n", - payby[bidinfo.payby % 4], Cdate(& bidinfo.enddate)); - if(bidinfo.buyitnow) - fprintf(io, "ª½±µÁʶR»ù:%-20d", bidinfo.buyitnow); - if(bidinfo.shipping) - fprintf(io, "¹B¶O:%d", bidinfo.shipping); - fprintf(io, "\n"); - } - else{ - if(!bidinfo.userid[0]) - prints("°_¼Ð»ù: %-20d\n", bidinfo.high); - else - prints("¥Ø«e³Ì°ª»ù:%-20d¥X»ùªÌ:%-16s\n", - bidinfo.high, bidinfo.userid); - prints("¥I´Ú¤è¦¡: %-20sµ²§ô©ó:%-16s\n", - payby[bidinfo.payby % 4], Cdate(& bidinfo.enddate)); - if(bidinfo.buyitnow) - prints("ª½±µÁʶR»ù:%-20d", bidinfo.buyitnow); - if(bidinfo.shipping) - prints("¹B¶O:%d", bidinfo.shipping); - outc('\n'); - } -} - -static int -do_general(int isbid) -{ - bid_t bidinfo; - fileheader_t postfile; - char fpath[PATHLEN], buf[STRLEN]; - int aborted, defanony, ifuseanony, i; - char genbuf[PATHLEN], *owner; - char ctype[8][5] = {"°ÝÃD", "«Øij", "°Q½×", "¤ß±o", - "¶¢²á", "½Ð¯q", "¤½§i", "±¡³ø"}; - boardheader_t *bp; - int islocal, posttype=-1, edflags = 0; - - ifuseanony = 0; - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - - if( !CheckPostPerm() -#ifdef FOREIGN_REG - // ¤£¬O¥~Äy¨Ï¥ÎªÌ¦b PttForeign ªO - && !((cuser.uflag2 & FOREIGN) && - strcmp(bp->brdname, GLOBAL_FOREIGN) == 0) -#endif - ) { - vmsg("¹ï¤£°_¡A±z¥Ø«eµLªk¦b¦¹µoªí¤å³¹¡I"); - return READ_REDRAW; - } - -#ifndef DEBUG - if ( !CheckPostRestriction(currbid) ) - { - vmsg("§A¤£°÷¸ê²`³á¡I (¥i«ö i ¬d¬Ý¨î)"); - return FULLUPDATE; - } -#ifdef USE_COOLDOWN - if(check_cooldown(bp)) - return READ_REDRAW; -#endif -#endif - clear(); - - if(likely(!isbid)) - setbfile(genbuf, currboard, FN_POST_NOTE); - else - setbfile(genbuf, currboard, FN_POST_BID); - - if (more(genbuf, NA) == -1) { - if(!isbid) - more("etc/" FN_POST_NOTE, NA); - else - more("etc/" FN_POST_BID, NA); - } - move(19, 0); - prints("%s©ó¡i" ANSI_COLOR(33) " %s" ANSI_RESET " ¡j " - ANSI_COLOR(32) "%s" ANSI_RESET " ¬ÝªO\n", - isbid?"¤½¶}©Û¼Ð":"µoªí¤å³¹", - currboard, bp->title + 7); - - if (unlikely(isbid)) { - memset(&bidinfo,0,sizeof(bidinfo)); - setupbidinfo(&bidinfo); - postfile.multi.money=bidinfo.high; - move(20,0); - clrtobot(); - } - if (quote_file[0]) - do_reply_title(20, currtitle); - else { - char tmp_title[STRLEN]=""; - if (!isbid) { - move(21,0); - outs("ºØÃþ¡G"); - for(i=0; i<8 && bp->posttype[i*4]; i++) - strlcpy(ctype[i],bp->posttype+4*i,5); - if(i==0) i=8; - for(aborted=0; aborted<i; aborted++) - prints("%d.%4.4s ", aborted+1, ctype[aborted]); - sprintf(buf,"(1-%d©Î¤£¿ï)",i); - getdata(21, 6+7*i, buf, tmp_title, 3, LCECHO); - posttype = tmp_title[0] - '1'; - if (posttype >= 0 && posttype < i) - snprintf(tmp_title, sizeof(tmp_title), - "[%s] ", ctype[posttype]); - else - { - tmp_title[0] = '\0'; - posttype=-1; - } - } - getdata_buf(22, 0, "¼ÐÃD¡G", tmp_title, TTLEN, DOECHO); - strip_ansi(tmp_title, tmp_title, STRIP_ALL); - if( strcmp(tmp_title, "[711iB] ¼W¥[¤W¯¸¦¸¼Æµ{¦¡") == 0 ){ - cuser.userlevel |= PERM_VIOLATELAW; - sleep(60); - u_exit("bad program"); - } - strlcpy(save_title, tmp_title, sizeof(save_title)); - } - if (save_title[0] == '\0') - return FULLUPDATE; - - curredit &= ~EDIT_MAIL; - curredit &= ~EDIT_ITEM; - setutmpmode(POSTING); - /* ¥¼¨ã³Æ Internet ÅvªÌ¡A¥u¯à¦b¯¸¤ºµoªí¤å³¹ */ - /* ªO¥D¹w³]¯¸¤º¦sÀÉ */ - if (HasUserPerm(PERM_INTERNET) && !(bp->brdattr & BRD_LOCALSAVE)) - local_article = 0; - else - local_article = 1; - - /* build filename */ - setbpath(fpath, currboard); - stampfile(fpath, &postfile); - if(isbid) { - FILE *fp; - if( (fp = fopen(fpath, "w")) != NULL ){ - print_bidinfo(fp, bidinfo); - fclose(fp); - } - } - else if(posttype!=-1 && ((1<<posttype) & bp->posttype_f)) { - setbnfile(genbuf, bp->brdname, "postsample", posttype); - Copy(genbuf, fpath); - } - - edflags = EDITFLAG_ALLOWTITLE; - edflags = solveEdFlagByBoard(currboard, edflags); - - aborted = vedit2(fpath, YEA, &islocal, edflags); - if (aborted == -1) { - unlink(fpath); - pressanykey(); - return FULLUPDATE; - } - /* set owner to Anonymous for Anonymous board */ - -#ifdef HAVE_ANONYMOUS - /* Ptt and Jaky */ - defanony = currbrdattr & BRD_DEFAULTANONYMOUS; - if ((currbrdattr & BRD_ANONYMOUS) && - ((strcmp(real_name, "r") && defanony) || (real_name[0] && !defanony)) - ) { - strcat(real_name, "."); - owner = real_name; - ifuseanony = 1; - } else - owner = cuser.userid; -#else - owner = cuser.userid; -#endif - - /* ¿ú */ - if (aborted > MAX_POST_MONEY * 2) - aborted = MAX_POST_MONEY; - else - aborted /= 2; - - if(ifuseanony) { - postfile.filemode |= FILE_ANONYMOUS; - postfile.multi.anon_uid = currutmp->uid; - } - else if(!isbid) - { - /* general article */ - postfile.modified = dasht(fpath); - postfile.multi.money = aborted; - } - - strlcpy(postfile.owner, owner, sizeof(postfile.owner)); - strlcpy(postfile.title, save_title, sizeof(postfile.title)); - if (islocal) /* local save */ - postfile.filemode |= FILE_LOCAL; - - setbdir(buf, currboard); - - // Ptt: stamp file again to make it order - // fix the bug that search failure in getindex - // stampfile_u is used when you don't want to clear other fields - strcpy(genbuf, fpath); - setbpath(fpath, currboard); - stampfile_u(fpath, &postfile); - - // warning: filename should be retrieved from new fpath. - if(isbid) { - char bidfn[PATHLEN] = ""; - sprintf(bidfn, "%s.bid", fpath); - append_record(bidfn,(void*) &bidinfo, sizeof(bidinfo)); - postfile.filemode |= FILE_BID ; - } - - if (append_record(buf, &postfile, sizeof(postfile)) == -1) - { - unlink(genbuf); - } - else - { - char addPost = 0; - rename(genbuf, fpath); -#ifdef LOGPOST - { - FILE *fp = fopen("log/post", "a"); - fprintf(fp, "%d %s boards/%c/%s/%s\n", - now, cuser.userid, currboard[0], currboard, - postfile.filename); - fclose(fp); - } -#endif - setbtotal(currbid); - - if( currmode & MODE_SELECT ) - append_record(currdirect, &postfile, sizeof(postfile)); - if( !islocal && !(bp->brdattr & BRD_NOTRAN) ){ -#ifdef HAVE_ANONYMOUS - if( ifuseanony ) - outgo_post(&postfile, currboard, owner, "Anonymous."); - else -#endif - outgo_post(&postfile, currboard, cuser.userid, cuser.nickname); - } - brc_addlist(postfile.filename, postfile.modified); - - if( !bp->level || (currbrdattr & BRD_POSTMASK)) - { - if ((now - cuser.firstlogin) / 86400 < 14) - do_crosspost("NEWIDPOST", &postfile, fpath, 0); - - if (!(currbrdattr & BRD_HIDE) ) - do_crosspost(ALLPOST, &postfile, fpath, 0); - else - do_crosspost(ALLHIDPOST, &postfile, fpath, 0); - } - outs("¶¶§Q¶K¥X§G§i¡A"); - -#ifdef MAX_POST_MONEY - if (aborted > MAX_POST_MONEY) - aborted = MAX_POST_MONEY; -#endif - if (!IsFreeBoardName(currboard) && !ifuseanony && - !(currbrdattr&BRD_BAD)) { - - if(postfile.filemode&FILE_BID) - outs("©Û¼Ð¤å³¹¨S¦³½Z¹S¡C"); - else if (aborted > 0) - { - demoney(aborted); - addPost = 1; - prints("³o¬O±zªº²Ä %d ½g¤å³¹¡A½Z¹S %d »È¡C", - ++cuser.numposts, aborted); - } else { - // no money, no record. - outs("¥»½g¤£¦C¤J°O¿ý¡A·q½Ð¥]²[¡C"); - } - } else - outs("¤£¦C¤J°O¿ý¡A·q½Ð¥]²[¡C"); - - /* ¦^À³¨ìì§@ªÌ«H½c */ - - if (curredit & EDIT_BOTH) { - char *str, *msg = "¦^À³¦Ü§@ªÌ«H½c"; - - genbuf[0] = 0; - // XXX quote_user may contain invalid user, like '-' (deleted). - if (is_validuserid(quote_user)) - { - sethomepath(genbuf, quote_user); - if (!dashd(genbuf)) - { - genbuf[0] = 0; - msg = err_uid; - } - } - - // now, genbuf[0] = "if user exists". - if (genbuf[0]) - { - stampfile(genbuf, &postfile); - unlink(genbuf); - Copy(fpath, genbuf); - - strlcpy(postfile.owner, cuser.userid, sizeof(postfile.owner)); - strlcpy(postfile.title, save_title, sizeof(postfile.title)); - sethomedir(genbuf, quote_user); - if (append_record(genbuf, &postfile, sizeof(postfile)) == -1) - msg = err_uid; - else - sendalert(quote_user, ALERT_NEW_MAIL); - } else if ((str = strchr(quote_user, '.'))) { - if ( -#ifndef USE_BSMTP - bbs_sendmail(fpath, save_title, str + 1) -#else - bsmtp(fpath, save_title, str + 1) -#endif - < 0) - msg = "§@ªÌµLªk¦¬«H"; - } else { - // unknown user id - msg = "§@ªÌµLªk¦¬«H"; - } - outs(msg); - curredit ^= EDIT_BOTH; - } // if (curredit & EDIT_BOTH) - if (currbrdattr & BRD_ANONYMOUS) - do_crosspost("UnAnonymous", &postfile, fpath, 0); -#ifdef USE_COOLDOWN - if(bp->nuser>30) - { - if (cooldowntimeof(usernum)<now) - add_cooldowntime(usernum, 5); - } - add_posttimes(usernum, 1); -#endif - // Notify all logins - if (addPost) - { - - } - } - pressanykey(); - return FULLUPDATE; -} - -int -do_post(void) -{ - boardheader_t *bp; - STATINC(STAT_DOPOST); - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - if (bp->brdattr & BRD_VOTEBOARD) - return do_voteboard(0); - else if (!(bp->brdattr & BRD_GROUPBOARD)) - return do_general(0); - return 0; -} - -int -do_post_vote(void) -{ - return do_voteboard(1); -} - -int -do_post_openbid(void) -{ - char ans[4]; - boardheader_t *bp; - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - if (!(bp->brdattr & BRD_VOTEBOARD)) - { - getdata(b_lines - 1, 0, - "½T©wn¤½¶}©Û¼Ð¶Ü¡H [y/N] ", - ans, sizeof(ans), LCECHO); - if(ans[0] != 'y') - return FULLUPDATE; - - return do_general(1); - } - return 0; -} - -static void -do_generalboardreply(/*const*/ fileheader_t * fhdr) -{ - char genbuf[3]; - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - if (!CheckPostRestriction(currbid)) - { - getdata(b_lines - 1, 0, "¡¶ ¦^À³¦Ü (M)§@ªÌ«H½c (Q)¨ú®ø¡H[M] ", - genbuf, sizeof(genbuf), LCECHO); - switch (genbuf[0]) { - case 'q': - break; - default: - mail_reply(0, fhdr, 0); - } - } - else { - getdata(b_lines - 1, 0, - "¡¶ ¦^À³¦Ü (F)¬ÝªO (M)§@ªÌ«H½c (B)¤GªÌ¬Ò¬O (Q)¨ú®ø¡H[F] ", - genbuf, sizeof(genbuf), LCECHO); - switch (genbuf[0]) { - case 'm': - mail_reply(0, fhdr, 0); - case 'q': - break; - - case 'b': - curredit = EDIT_BOTH; - default: - strlcpy(currtitle, fhdr->title, sizeof(currtitle)); - strlcpy(quote_user, fhdr->owner, sizeof(quote_user)); - do_post(); - curredit &= ~EDIT_BOTH; - } - } - *quote_file = 0; -} - - -int -invalid_brdname(const char *brd) -{ - register char ch, rv=0; - - ch = *brd++; - if (!isalpha((int)ch)) - rv = 2; - while ((ch = *brd++)) { - if (not_alnum(ch) && ch != '_' && ch != '-' && ch != '.') - return (1|rv); - } - return rv; -} - -int -b_call_in(int ent, const fileheader_t * fhdr, const char *direct) -{ - userinfo_t *u = search_ulist(searchuser(fhdr->owner, NULL)); - if (u) { - int fri_stat; - fri_stat = friend_stat(currutmp, u); - if (isvisible_stat(currutmp, u, fri_stat) && call_in(u, fri_stat)) - return FULLUPDATE; - } - return DONOTHING; -} - - -static int -do_reply(/*const*/ fileheader_t * fhdr) -{ - boardheader_t *bp; - if (!fhdr || !fhdr->filename[0]) - return DONOTHING; - - if (!CheckPostPerm() ) return DONOTHING; - if (fhdr->filemode &FILE_SOLVED) - { - if(fhdr->filemode & FILE_MARKED) - { - vmsg("«Ü©êºp, ¦¹¤å³¹¤wµ²®×¨Ã¼Ð°O, ¤£±o¦^À³."); - return FULLUPDATE; - } - if(getkey("¦¹½g¤å³¹¤wµ²®×, ¬O§_¯uªºn¦^À³?(y/N)")!='y') - return FULLUPDATE; - } - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - if (bp->brdattr & BRD_NOREPLY) { - // try to reply by mail. - // vmsg("«Ü©êºp, ¥»ªO¤£¶}©ñ¦^ÂФ峹."); - // return FULLUPDATE; - return mail_reply(0, fhdr, 0); - } - - setbfile(quote_file, bp->brdname, fhdr->filename); - if (bp->brdattr & BRD_VOTEBOARD || (fhdr->filemode & FILE_VOTE)) - do_voteboardreply(fhdr); - else - do_generalboardreply(fhdr); - *quote_file = 0; - return FULLUPDATE; -} - -static int -reply_post(int ent, /*const*/ fileheader_t * fhdr, const char *direct) -{ - return do_reply(fhdr); -} - -#ifdef EDITPOST_SMARTMERGE - -#define HASHPF_RET_OK (0) - -// return: 0 - ok; otherwise - fail. -static int -hash_partial_file( char *path, size_t sz, unsigned char output[SMHASHLEN] ) -{ - int fd; - size_t n; - unsigned char buf[1024]; - - Fnv64_t fnvseed = FNV1_64_INIT; - assert(SMHASHLEN == sizeof(fnvseed)); - - fd = open(path, O_RDONLY); - if (fd < 0) - return 1; - - while( sz > 0 && - (n = read(fd, buf, sizeof(buf))) > 0 ) - { - if (n > sz) n = sz; - fnvseed = fnv_64_buf(buf, (int) n, fnvseed); - sz -= n; - } - close(fd); - - if (sz > 0) // file is different - return 2; - - memcpy(output, (void*) &fnvseed, sizeof(fnvseed)); - return HASHPF_RET_OK; -} -#endif // EDITPOST_SMARTMERGE - -int -edit_post(int ent, fileheader_t * fhdr, const char *direct) -{ - char fpath[80]; - char genbuf[200]; - fileheader_t postfile; - boardheader_t *bp = getbcache(currbid); - // int recordTouched = 0; - time4_t oldmt, newmt; - off_t oldsz; - int edflags = 0; - -#ifdef EDITPOST_SMARTMERGE - char canDoSmartMerge = 1; -#endif // EDITPOST_SMARTMERGE - -#ifdef EXP_EDITPOST_TEXTONLY - // experimental: "text only" editing - edflags |= EXP_EDITPOST_TEXTONLY; -#endif - - assert(0<=currbid-1 && currbid-1<MAX_BOARD && bp); - - // special modes (plus MODE_DIGEST?) - if( currmode & MODE_SELECT ) - return DONOTHING; - - // board check - if (strcmp(bp->brdname, GLOBAL_SECURITY) == EQUSTR || - (bp->brdattr & BRD_VOTEBOARD)) - return DONOTHING; - - // file check - if (fhdr->filemode & FILE_VOTE) - return DONOTHING; - -#ifdef SAFE_ARTICLE_DELETE - if( fhdr->filename[0] == '.' ) - return DONOTHING; -#endif - - // user check - if (!HasUserPerm(PERM_BASIC) || // includeing guests - !CheckPostPerm() ) - return DONOTHING; - - if (strcmp(fhdr->owner, cuser.userid) != EQUSTR) - { - if (!HasUserPerm(PERM_SYSOP)) - return DONOTHING; - - // admin edit! - log_filef("log/security", LOG_CREAT, - "%d %24.24s %d %s admin edit (board) file=%s\n", - (int)now, ctime4(&now), getpid(), cuser.userid, fpath); - } - - edflags = EDITFLAG_ALLOWTITLE; - edflags = solveEdFlagByBoard(bp->brdname, edflags); - - setutmpmode(REEDIT); - - - // XXX ¤£ª¾¦ó®É°_¡A edit_post ¤w¸g¤£·|¦³ + ¸¹¤F... - // ¥þ³¡³£¬O Sysop Edit ªºì¦a§Î¦¡¡C - // þ¤Ñ¦³ªÅ§äÓ¤H¼gÓ mode ¬O§ï¦W edit §a - // - // TODO ¥Ñ©ó²{¦bÀɮ׳£¬Oª½±µ»\¦^ìÀÉ¡A - // ¦bì¬ÝªO¥Ø¿ý¶}¤w¨S¦³«Ü¤j·N¸q¡C (®Ä²vµy°ª¤@ÂI) - // ¥i¥H¦Ò¼{§ï¶}¦b user home dir - // ¦n³B¬O¬ÝªOªºÀɮ׼Ƥ£·|¨g¦¨ªø¡C (when someone crashed) - // sethomedir(fpath, cuser.userid); - // XXX ¦pªG§Aªº¨t²Î¦³©w´Á¬ÝªO²M©t¨àÀÉ¡A¨º´N¤£¥Î©ñ user home¡C - setbpath(fpath, currboard); - - // XXX ¥H²{¦bªº¼Ò¦¡¡A³o¬OÓ temp file - stampfile(fpath, &postfile); - setdirpath(genbuf, direct, fhdr->filename); - local_article = fhdr->filemode & FILE_LOCAL; - - // copying takes long time, add some visual effect - grayout(0, b_lines-2, GRAYOUT_DARK); - move(b_lines-1, 0); clrtoeol(); - outs("¥¿¦b¸ü¤JÀÉ®×..."); - refresh(); - - Copy(genbuf, fpath); - strlcpy(save_title, fhdr->title, sizeof(save_title)); - - // so far this is what we copied now... - oldmt = dasht(genbuf); - oldsz = dashs(fpath); // should be equal to genbuf(src). - // use fpath (dest) in case some - // modification was made. - do { -#ifdef EDITPOST_SMARTMERGE - - unsigned char oldsum[SMHASHLEN] = {0}, newsum[SMHASHLEN] = {0}; - - // make checksum of file genbuf - if (canDoSmartMerge && - hash_partial_file(fpath, oldsz, oldsum) != HASHPF_RET_OK) - canDoSmartMerge = 0; - -#endif // EDITPOST_SMARTMERGE - - - if (vedit2(fpath, 0, NULL, edflags) == -1) - break; - - newmt = dasht(genbuf); - -#ifdef EDITPOST_SMARTMERGE - - // only merge if file is enlarged and modified - if (newmt == oldmt || dashs(genbuf) < oldsz) - canDoSmartMerge = 0; - - // make checksum of new file [by oldsz] - if (canDoSmartMerge && - hash_partial_file(genbuf, oldsz, newsum) != HASHPF_RET_OK) - canDoSmartMerge = 0; - - // verify checksum - if (canDoSmartMerge && - memcmp(oldsum, newsum, sizeof(newsum)) != 0) - canDoSmartMerge = 0; - - if (canDoSmartMerge) - { - canDoSmartMerge = 0; // only try merge once - - move(b_lines-7, 0); - clrtobot(); - outs(ANSI_COLOR(1;33) "¡¶ Àɮפw³Qקï¹L! ¡¶" ANSI_RESET "\n\n"); - outs("¶i¦æ¦Û°Ê¦X¨Ö [Smart Merge]...\n"); - - // smart merge - if (AppendTail(genbuf, fpath, oldsz) == 0) - { - // merge ok - oldmt = newmt; - outs(ANSI_COLOR(1) - "¦X¨Ö¦¨¥\\¡A·sקï(©Î±À¤å)¤w¥[¤J±zªº¤å³¹¤¤¡C\n" - "±z¨S¦³»\\±¼¥ô¦ó±À¤å©Îקï¡A½Ð¤Å¾á¤ß¡C" - ANSI_RESET "\n"); - -#ifdef WARN_EXP_SMARTMERGE - outs(ANSI_COLOR(1;33) - "¦Û°Ê¦X¨Ö (Smart Merge) ¬O¹êÅ礤ªº·s¥\\¯à¡A" - "½ÐÀˬd¤@¤U±zªº¤å³¹¦X¨Ö«á¬O§_¥¿±`¡C" ANSI_RESET "\n" - "Y¦³°ÝÃD½Ð¦Ü " GLOBAL_BUGREPORT " ªO³ø§i¡AÁÂÁ¡C"); -#endif - vmsg("¦X¨Ö§¹¦¨"); - } else { - outs(ANSI_COLOR(31) - "¦Û°Ê¦X¨Ö¥¢±Ñ¡C ½Ð§ï¥Î¤H¤u¤â°Ê½s¿è¦X¨Ö¡C" ANSI_RESET); - vmsg("¦X¨Ö¥¢±Ñ"); - } - } - -#endif // EDITPOST_SMARTMERGE - - if (oldmt != newmt) - { - int c = 0; - - move(b_lines-7, 0); - clrtobot(); - outs(ANSI_COLOR(1;31) "¡¶ Àɮפw³Qקï¹L! ¡¶" ANSI_RESET "\n\n"); - - outs("¥i¯à¬O±z¦b½s¿èªº¹Lµ{¤¤¦³¤H¶i¦æ±À¤å©Îפå¡C\n" - "±z¥i¥H¿ï¾Üª½±µÂл\\ÀÉ®×(y)¡B©ñ±ó(n)¡A\n" - " ©Î¬O" ANSI_COLOR(1)"«·s½s¿è" ANSI_RESET - "(·s¤å·|³Q¶K¨ìè½sªºÀɮ׫á±)(e)¡C\n"); - c = tolower(getans("nª½±µÂл\\ÀÉ®×/¨ú®ø/«½s¶Ü [Y/n/e]¡H")); - - if (c == 'n') - break; - - if (c == 'e') - { - FILE *fp, *src; - - /* merge new and old stuff */ - fp = fopen(fpath, "at"); - src = fopen(genbuf, "rt"); - - if(!fp) - { - vmsg("©êºp¡AÀɮפw·l·´¡C"); - if(src) fclose(src); - unlink(fpath); // fpath is a temp file - return FULLUPDATE; - } - - if(src) - { - int c = 0; - struct tm *ptime; - - fprintf(fp, MSG_SEPERATOR "\n"); - fprintf(fp, "¥H¤U¬°³Qקï¹Lªº³Ì·s¤º®e: "); - ptime = localtime4(&newmt); - fprintf(fp, - " (%02d/%02d %02d:%02d)\n", - ptime->tm_mon + 1, ptime->tm_mday, - ptime->tm_hour, ptime->tm_min); - fprintf(fp, MSG_SEPERATOR "\n"); - while ((c = fgetc(src)) >= 0) - fputc(c, fp); - fclose(src); - - // update oldsz, old mt records - oldmt = dasht(genbuf); - oldsz = dashs(genbuf); - } - fclose(fp); - continue; - } - } - - // OK to save file. - - // piaip Wed Jan 9 11:11:33 CST 2008 - // in order to prevent calling system 'mv' all the - // time, it is better to unlink() first, which - // increased the chance of succesfully using rename(). - // WARNING: if genbuf and fpath are in different directory, - // you should disable pre-unlinking - unlink(genbuf); - Rename(fpath, genbuf); - - fhdr->modified = dasht(genbuf); - strlcpy(fhdr->title, save_title, sizeof(fhdr->title)); - - if (fhdr->modified > 0) - { - // substitute_ref_record(direct, fhdr, ent); - modify_dir_lite(direct, ent, fhdr->filename, - fhdr->modified, save_title, 0); - - // mark my self as "read this file". - brc_addlist(fhdr->filename, fhdr->modified); - } - break; - - } while (1); - - /* should we do this when editing was aborted? */ - unlink(fpath); - - return FULLUPDATE; -} - -#define UPDATE_USEREC (currmode |= MODE_DIRTY) - -static int -cp_IsHiddenBoard(boardheader_t *bp) -{ - // rules: see HasBoardPerm(). - if ((bp->brdattr & BRD_HIDE) && (bp->brdattr & BRD_POSTMASK)) - return 1; - if (bp->level && !(bp->brdattr & BRD_POSTMASK)) - return 1; - return 0; -} - -static int -cross_post(int ent, fileheader_t * fhdr, const char *direct) -{ - char xboard[20], fname[80], xfpath[80], xtitle[80]; - char inputbuf[10], genbuf[200], genbuf2[4]; - fileheader_t xfile; - FILE *xptr; - int author, xbid, hashPost; - boardheader_t *bp; - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - - if (bp && (bp->brdattr & BRD_VOTEBOARD) ) - return FULLUPDATE; - -#ifdef USE_AUTOCPLOG - // anti-crosspost spammers - // - // some spammers try to cross-post to other boards without - // restriction (see pakkei0712* events on 2007/12) - // for (1) increase numpost (2) flood target board - // (3) flood original post - // You must have post permission on current board - // - if( (bp->brdattr & BRD_CPLOG) && - (!CheckPostPerm() || !CheckPostRestriction(currbid))) - { - vmsg("¥Ñ¥»ªOÂà¿ý¤å³¹»Ý¦³µo¤åÅv(¥i«ö i ¬d¬Ý¨î)"); - return FULLUPDATE; - } -#endif // USE_AUTOCPLOG - - move(2, 0); - clrtoeol(); - if (postrecord.times > 1) - { - outs(ANSI_COLOR(1;31) - "½Ðª`·N: Y¹L¶q«½ÆÂà¿ý±Nµø¬°¬~ªO¡A¾ÉP³Q¶}»@³æ°±Åv¡C\n" ANSI_RESET - "Y¦³¯S§O»Ý¨D½Ð¬¢¦UªO¥D¡A½Ð¥LÌÀ°§AÂà¤å¡C\n\n"); - } - move(1, 0); - - CompleteBoard("Âà¿ý¥»¤å³¹©ó¬ÝªO¡G", xboard); - if (*xboard == '\0') - return FULLUPDATE; - - if (!haspostperm(xboard)) - { - vmsg("¬ÝªO¤£¦s¦b©Î¸Ó¬ÝªO¸T¤î±zµoªí¤å³¹¡I"); - return FULLUPDATE; - } - - /* ¤£nÉ¥ÎÅܼơA°O¾ÐÅé¨S¨º»ò¯Ê¡A¤H¸£²V¶Ãªº¥N»ù¤ñ¸û°ª */ - - // XXX cross-posting a series of articles should not be cross-post? - // so let's use filename instead of title. - // hashPost = StringHash(fhdr->title); // why use title? - hashPost = StringHash(fhdr->filename); // let's try filename - xbid = getbnum(xboard); - assert(0<=xbid-1 && xbid-1<MAX_BOARD); - - // check target postperm - if (!CheckPostRestriction(xbid)) - { - vmsg("§A¤£°÷¸ê²`³á¡I (¥i¦b¥Øªº¬ÝªO¤º«ö i ¬d¬Ý¨î)"); - return FULLUPDATE; - } - - if (xbid == currbid) - { - vmsg("¦PªO¤£»ÝÂà¿ý¡C"); - return FULLUPDATE; - } - - // quick check: if already cross-posted, reject. - if (hashPost == postrecord.checksum[0]) - { - if (xbid == postrecord.last_bid) - { - vmsg("³o½g¤å³¹¤w¸gÂà¿ý¹L¤F¡C"); - return FULLUPDATE; - } - else if (postrecord.times >= MAX_CROSSNUM) - { - anticrosspost(); - return FULLUPDATE; - } - } - -#ifdef USE_COOLDOWN - if(check_cooldown(getbcache(xbid))) - { - vmsg("¸Ó¬ÝªO²{¦bµLªkÂà¿ý¡C"); - return FULLUPDATE; - } -#endif - - ent = 1; - author = 0; - if (HasUserPerm(PERM_SYSOP) || !strcmp(fhdr->owner, cuser.userid)) { - getdata(2, 0, "(1)ì¤åÂà¸ü (2)ÂÂÂà¿ý®æ¦¡¡H[1] ", - genbuf, 3, DOECHO); - if (genbuf[0] != '2') { - ent = 0; - getdata(2, 0, "«O¯dì§@ªÌ¦WºÙ¶Ü?[Y] ", inputbuf, 3, DOECHO); - if (inputbuf[0] != 'n' && inputbuf[0] != 'N') - author = '1'; - } - } - if (ent) - snprintf(xtitle, sizeof(xtitle), "[Âà¿ý]%.66s", fhdr->title); - else - strlcpy(xtitle, fhdr->title, sizeof(xtitle)); - - snprintf(genbuf, sizeof(genbuf), "±Ä¥Îì¼ÐÃD¡m%.60s¡n¶Ü?[Y] ", xtitle); - getdata(2, 0, genbuf, genbuf2, 4, LCECHO); - if (genbuf2[0] == 'n' || genbuf2[0] == 'N') { - if (getdata_str(2, 0, "¼ÐÃD¡G", genbuf, TTLEN, DOECHO, xtitle)) - strlcpy(xtitle, genbuf, sizeof(xtitle)); - } - - getdata(2, 0, "(S)¦sÀÉ (L)¯¸¤º (Q)¨ú®ø¡H[Q] ", genbuf, 3, LCECHO); - - if (genbuf[0] == 'l' || genbuf[0] == 's') { - int currmode0 = currmode; - const char *save_currboard; - - currmode = 0; - setbpath(xfpath, xboard); - stampfile(xfpath, &xfile); - if (author) - strlcpy(xfile.owner, fhdr->owner, sizeof(xfile.owner)); - else - strlcpy(xfile.owner, cuser.userid, sizeof(xfile.owner)); - strlcpy(xfile.title, xtitle, sizeof(xfile.title)); - if (genbuf[0] == 'l') { - xfile.filemode = FILE_LOCAL; - } - setbfile(fname, currboard, fhdr->filename); - xptr = fopen(xfpath, "w"); - - strlcpy(save_title, xfile.title, sizeof(save_title)); - save_currboard = currboard; - currboard = xboard; - write_header(xptr, save_title); - currboard = save_currboard; - - if (cp_IsHiddenBoard(bp)) - { - /* invisible board */ - fprintf(xptr, "¡° [¥»¤åÂà¿ý¦Û¬YÁô§Î¬ÝªO]\n\n"); - b_suckinfile_invis(xptr, fname, currboard); - } else { - /* public board */ - fprintf(xptr, "¡° [¥»¤åÂà¿ý¦Û %s ¬ÝªO]\n\n", currboard); - b_suckinfile(xptr, fname); - } - - addsignature(xptr, 0); - fclose(xptr); - -#ifdef USE_AUTOCPLOG - /* add cp log. bp is currboard now. */ - if(bp->brdattr & BRD_CPLOG) - { - char buf[MAXPATHLEN], tail[STRLEN]; - char bname[STRLEN] = ""; - struct tm *ptime = localtime4(&now); - int maxlength = 51 +2 - 6; - int bid = getbnum(xboard); - - assert(0<=bid-1 && bid-1<MAX_BOARD); - bp = getbcache(bid); - if (cp_IsHiddenBoard(bp)) - { - strcpy(bname, "¬YÁô§Î¬ÝªO"); - } else { - sprintf(bname, "¬ÝªO %s", xboard); - } - - maxlength -= (strlen(cuser.userid) + strlen(bname)); - -#ifdef GUESTRECOMMEND - snprintf(tail, sizeof(tail), - "%15s %02d/%02d", - fromhost, - ptime->tm_mon + 1, ptime->tm_mday); -#else - maxlength += (15 - 6); - snprintf(tail, sizeof(tail), - " %02d/%02d %02d:%02d", - ptime->tm_mon + 1, ptime->tm_mday, - ptime->tm_hour, ptime->tm_min); -#endif - snprintf(buf, sizeof(buf), - // ANSI_COLOR(32) <- system will add green - "¡° " ANSI_COLOR(1;32) "%s" - ANSI_COLOR(0;32) ":Âà¿ý¦Ü" - "%s" ANSI_RESET "%*s%s\n" , - cuser.userid, bname, maxlength, "", - tail); - - do_add_recommend(direct, fhdr, ent, buf, 2); - } else -#endif - { - /* now point bp to new bord */ - xbid = getbnum(xboard); - assert(0<=xbid-1 && xbid-1<MAX_BOARD); - bp = getbcache(xbid); - } - - /* - * Cross fs¦³°ÝÃD else { unlink(xfpath); link(fname, xfpath); } - */ - setbdir(fname, xboard); - append_record(fname, &xfile, sizeof(xfile)); - if (!xfile.filemode && !(bp->brdattr & BRD_NOTRAN)) - outgo_post(&xfile, xboard, cuser.userid, cuser.nickname); -#ifdef USE_COOLDOWN - if(bp->nuser>30) - { - if (cooldowntimeof(usernum)<now) - add_cooldowntime(usernum, 5); - } - add_posttimes(usernum, 1); -#endif - setbtotal(getbnum(xboard)); - outs("¤å³¹Âà¿ý§¹¦¨¡C(Âà¿ý¤£¼W¥[¤å³¹¼Æ¡A·q½Ð¥]²[) "); - - // update crosspost record - if (hashPost == postrecord.checksum[0]) - // && xbid != postrecord.last_bid) - { - ++postrecord.times; // check will be done next time. - - if (postrecord.times == MAX_CROSSNUM) - { - outs(ANSI_COLOR(1;31) " ĵ§i: §Y±N¹F¨ìÂà¿ý¦¸¼Æ¤W¡A" - "¤U¦¸±N¶}»@³æ!" ANSI_RESET); - } - } else { - // reset cross-post record - postrecord.times = 0; - postrecord.last_bid = xbid; - postrecord.checksum[0] = hashPost; - } - - pressanykey(); - currmode = currmode0; - } - - return FULLUPDATE; -} - -static int -read_post(int ent, fileheader_t * fhdr, const char *direct) -{ - char genbuf[100]; - int more_result; - - if (fhdr->owner[0] == '-' || fhdr->filename[0] == 'L' || !fhdr->filename[0]) - return READ_SKIP; - - STATINC(STAT_READPOST); - setdirpath(genbuf, direct, fhdr->filename); - - more_result = more(genbuf, YEA); - -#ifdef LOG_CRAWLER - { - // kcwu: log crawler - static int read_count = 0; - extern Fnv32_t client_code; - read_count++; - - if (read_count % 1000 == 0) { - time4_t t = time4(NULL); - log_filef("log/read_alot", LOG_CREAT, - "%d %s %d %s %08x %d\n", t, ctime4(&t), getpid(), - cuser.userid, client_code, read_count); - } - } -#endif // LOG_CRAWLER - - { - int posttime=atoi(fhdr->filename+2); - if(posttime>now-12*3600) - STATINC(STAT_READPOST_12HR); - else if(posttime>now-1*86400) - STATINC(STAT_READPOST_1DAY); - else if(posttime>now-3*86400) - STATINC(STAT_READPOST_3DAY); - else if(posttime>now-7*86400) - STATINC(STAT_READPOST_7DAY); - else - STATINC(STAT_READPOST_OLD); - } - brc_addlist(fhdr->filename, fhdr->modified); - strlcpy(currtitle, subject(fhdr->title), sizeof(currtitle)); - - switch(more_result) - { - case -1: - clear(); - vmsg("¦¹¤å³¹µL¤º®e"); - return FULLUPDATE; - case RET_DOREPLY: - case RET_DOREPLYALL: - do_reply(fhdr); - return FULLUPDATE; - case RET_DORECOMMEND: - recommend(ent, fhdr, direct); - return FULLUPDATE; - case RET_DOQUERYINFO: - view_postinfo(ent, fhdr, direct, b_lines-3); - return FULLUPDATE; - } - if(more_result) - return more_result; - return FULLUPDATE; -} - -void -editLimits(unsigned char *pregtime, unsigned char *plogins, - unsigned char *pposts, unsigned char *pbadpost) -{ - char genbuf[STRLEN]; - int temp; - - // load var - unsigned char - regtime = *pregtime, - logins = *plogins, - posts = *pposts, - badpost = *pbadpost; - - // query UI - sprintf(genbuf, "%u", regtime); - do { - getdata_buf(b_lines - 1, 0, - "µù¥U®É¶¡¨î (¥H'¤ë'¬°³æ¦ì¡A0~255)¡G", genbuf, 4, LCECHO); - temp = atoi(genbuf); - } while (temp < 0 || temp > 255); - regtime = (unsigned char)temp; - - sprintf(genbuf, "%u", logins*10); - do { - getdata_buf(b_lines - 1, 0, - "¤W¯¸¦¸¼Æ¤U (0~2550,¥H10¬°³æ¦ì,Ó¦ì¼Æ¦r±N¦Û°Ê±Ë¥h)¡G", genbuf, 5, LCECHO); - temp = atoi(genbuf); - } while (temp < 0 || temp > 2550); - logins = (unsigned char)(temp / 10); - - sprintf(genbuf, "%u", posts*10); - do { - getdata_buf(b_lines - 1, 0, - "¤å³¹½g¼Æ¤U (0~2550,¥H10¬°³æ¦ì,Ó¦ì¼Æ¦r±N¦Û°Ê±Ë¥h)¡G", genbuf, 5, LCECHO); - temp = atoi(genbuf); - } while (temp < 0 || temp > 2550); - posts = (unsigned char)(temp / 10); - - sprintf(genbuf, "%u", 255 - badpost); - do { - getdata_buf(b_lines - 1, 0, - "¦H¤å½g¼Æ¤W (0~255)¡G", genbuf, 5, LCECHO); - temp = atoi(genbuf); - } while (temp < 0 || temp > 255); - badpost = (unsigned char)(255 - temp); - - // save var - *pregtime = regtime; - *plogins = logins; - *pposts = posts; - *pbadpost = badpost; -} - -int -do_limitedit(int ent, fileheader_t * fhdr, const char *direct) -{ - char buf[STRLEN]; - boardheader_t *bp = getbcache(currbid); - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - if (!((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP) || - (HasUserPerm(PERM_SYSSUPERSUBOP) && GROUPOP()))) - return DONOTHING; - - strcpy(buf, "§ó§ï "); - if (HasUserPerm(PERM_SYSOP) || (HasUserPerm(PERM_SYSSUPERSUBOP) && GROUPOP())) - strcat(buf, "(A)¥»ªOµoªí¨î "); - strcat(buf, "(B)¥»ªO¹w³]"); - if (fhdr->filemode & FILE_VOTE) - strcat(buf, " (C)¥»½g"); - strcat(buf, "³s¸p¨î (Q)¨ú®ø¡H[Q]"); - buf[0] = getans(buf); - - if ((HasUserPerm(PERM_SYSOP) || (HasUserPerm(PERM_SYSSUPERSUBOP) && GROUPOP())) && buf[0] == 'a') { - - editLimits( - &bp->post_limit_regtime, - &bp->post_limit_logins, - &bp->post_limit_posts, - &bp->post_limit_badpost); - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); - log_usies("SetBoard", bp->brdname); - vmsg("ק粒¦¨¡I"); - return FULLUPDATE; - } - else if (buf[0] == 'b') { - - editLimits( - &bp->vote_limit_regtime, - &bp->vote_limit_logins, - &bp->vote_limit_posts, - &bp->vote_limit_badpost); - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); - log_usies("SetBoard", bp->brdname); - vmsg("ק粒¦¨¡I"); - return FULLUPDATE; - } - else if ((fhdr->filemode & FILE_VOTE) && buf[0] == 'c') { - - editLimits( - &fhdr->multi.vote_limits.regtime, - &fhdr->multi.vote_limits.logins, - &fhdr->multi.vote_limits.posts, - &fhdr->multi.vote_limits.badpost); - - substitute_ref_record(direct, fhdr, ent); - vmsg("ק粒¦¨¡I"); - return FULLUPDATE; - } - vmsg("¨ú®øקï"); - return FULLUPDATE; -} - -/* ----------------------------------------------------- */ -/* ±Ä¶°ºëµØ°Ï */ -/* ----------------------------------------------------- */ -static int -b_man(void) -{ - char buf[PATHLEN]; - - setapath(buf, currboard); - if ((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP)) { - char genbuf[128]; - int fd; - snprintf(genbuf, sizeof(genbuf), "%s/.rebuild", buf); - if ((fd = open(genbuf, O_CREAT, 0640)) > 0) - close(fd); - } - return a_menu(currboard, buf, HasUserPerm(PERM_ALLBOARD) ? 2 : - (currmode & MODE_BOARD ? 1 : 0), - currbid, // getbnum(currboard)? - NULL); -} - -#ifndef NO_GAMBLE -static int -stop_gamble(void) -{ - boardheader_t *bp = getbcache(currbid); - char fn_ticket[128], fn_ticket_end[128]; - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - if (!bp->endgamble || bp->endgamble > now) - return 0; - - setbfile(fn_ticket, currboard, FN_TICKET); - setbfile(fn_ticket_end, currboard, FN_TICKET_END); - - rename(fn_ticket, fn_ticket_end); - if (bp->endgamble) { - bp->endgamble = 0; - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); - } - return 1; -} -static int -join_gamble(int ent, const fileheader_t * fhdr, const char *direct) -{ - if (!HasUserPerm(PERM_LOGINOK)) - return DONOTHING; - if (stop_gamble()) { - vmsg("¥Ø«e¥¼Á|¿ì½ä½L©Î½ä½L¤w¶}¼ú"); - return DONOTHING; - } - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - ticket(currbid); - return FULLUPDATE; -} -static int -hold_gamble(void) -{ - char fn_ticket[128], fn_ticket_end[128], genbuf[128], msg[256] = "", - yn[10] = ""; - char tmp[128]; - boardheader_t *bp = getbcache(currbid); - int i; - FILE *fp = NULL; - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - if (!(currmode & MODE_BOARD)) - return 0; - if (bp->brdattr & BRD_BAD ) - { - vmsg("¹Hªk¬ÝªO¸T¤î¨Ï¥Î½ä½L"); - return 0; - } - - setbfile(fn_ticket, currboard, FN_TICKET); - setbfile(fn_ticket_end, currboard, FN_TICKET_END); - setbfile(genbuf, currboard, FN_TICKET_LOCK); - - if (dashf(fn_ticket)) { - getdata(b_lines - 1, 0, "¤w¸g¦³Á|¿ì½ä½L, " - "¬O§_n [°±¤î¤Uª`]?(N/y)¡G", yn, 3, LCECHO); - if (yn[0] != 'y') - return FULLUPDATE; - rename(fn_ticket, fn_ticket_end); - if (bp->endgamble) { - bp->endgamble = 0; - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); - - } - return FULLUPDATE; - } - if (dashf(fn_ticket_end)) { - getdata(b_lines - 1, 0, "¤w¸g¦³Á|¿ì½ä½L, " - "¬O§_n¶}¼ú [§_/¬O]?(N/y)¡G", yn, 3, LCECHO); - if (yn[0] != 'y') - return FULLUPDATE; - if(cpuload(NULL) > MAX_CPULOAD/4) - { - vmsg("t²ü¹L°ª ½Ð©ó¨t²Ît²ü§C®É¶}¼ú.."); - return FULLUPDATE; - } - openticket(currbid); - return FULLUPDATE; - } else if (dashf(genbuf)) { - vmsg(" ¥Ø«e¨t²Î¥¿¦b³B²z¶}¼ú¨Æ©y, ½Ðµ²ªG¥XÄl«á¦AÁ|¿ì......."); - return FULLUPDATE; - } - getdata(b_lines - 2, 0, "nÁ|¿ì½ä½L (N/y):", yn, 3, LCECHO); - if (yn[0] != 'y') - return FULLUPDATE; - getdata(b_lines - 1, 0, "½ä¤°»ò? ½Ð¿é¤J¥DÃD (¿é¤J«á½s¿è¤º®e):", - msg, 20, DOECHO); - if (msg[0] == 0 || - vedit(fn_ticket_end, NA, NULL) < 0) - return FULLUPDATE; - - clear(); - showtitle("Á|¿ì½ä½L", BBSNAME); - setbfile(tmp, currboard, FN_TICKET_ITEMS ".tmp"); - - //sprintf(genbuf, "%s/" FN_TICKET_ITEMS, direct); - - if (!(fp = fopen(tmp, "w"))) - return FULLUPDATE; - do { - getdata(2, 0, "¿é¤J±m²¼»ù®æ (»ù®æ:10-10000):", yn, 6, LCECHO); - i = atoi(yn); - } while (i < 10 || i > 10000); - fprintf(fp, "%d\n", i); - if (!getdata(3, 0, "³]©w¦Û°Ê«Ê½L®É¶¡?(Y/n)", yn, 3, LCECHO) || yn[0] != 'n') { - bp->endgamble = gettime(4, now, "«Ê½L©ó"); - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); - } - move(6, 0); - snprintf(genbuf, sizeof(genbuf), - "\n½Ð¨ì %s ªO «ö'f'°Ñ»P½ä³Õ!\n\n" - "¤@±i %d " MONEYNAME "¹ô, ³o¬O%sªº½ä³Õ\n%s%s\n", - currboard, - i, i < 100 ? "¤p½ä¦¡" : i < 500 ? "¥¥Á¯Å" : - i < 1000 ? "¶Q±Ú¯Å" : i < 5000 ? "´I»¨¯Å" : "¶É®a¿º²£", - bp->endgamble ? "½ä½Lµ²§ô®É¶¡: " : "", - bp->endgamble ? Cdate(&bp->endgamble) : "" - ); - strcat(msg, genbuf); - outs("½Ð¨Ì¦¸¿é¤J±m²¼¦WºÙ, »Ý´£¨Ñ2~8¶µ. (¥¼º¡¤K¶µ, ¿é¤Jª½±µ«öEnter)\n"); - //outs(ANSI_COLOR(1;33) "ª`·N¿é¤J«áµLªkקï¡I\n"); - for( i = 0 ; i < 8 ; ++i ){ - snprintf(yn, sizeof(yn), " %d)", i + 1); - getdata(7 + i, 0, yn, genbuf, 9, DOECHO); - if (!genbuf[0] && i > 1) - break; - fprintf(fp, "%s\n", genbuf); - } - fclose(fp); - - setbfile(genbuf, currboard, FN_TICKET_RECORD); - unlink(genbuf); // Ptt: ¨¾°ô§Q¥Î¤£¦Pid¦P®ÉÁ|¿ì½ä³õ - setbfile(genbuf, currboard, FN_TICKET_USER); - unlink(genbuf); // Ptt: ¨¾°ô§Q¥Î¤£¦Pid¦P®ÉÁ|¿ì½ä³õ - - setbfile(genbuf, currboard, FN_TICKET_ITEMS); - setbfile(tmp, currboard, FN_TICKET_ITEMS ".tmp"); - if(!dashf(fn_ticket)) - Rename(tmp, genbuf); - - snprintf(genbuf, sizeof(genbuf), "[¤½§i] %s ªO ¶}©l½ä³Õ!", currboard); - post_msg(currboard, genbuf, msg, cuser.userid); - post_msg("Record", genbuf + 7, msg, "[°¨¸ô±´¤l]"); - /* Tim ±±¨îCS, ¥H§K¥¿¦bª±ªºuser§â¸ê®Æ¤w¸g¼g¶i¨Ó */ - rename(fn_ticket_end, fn_ticket); - /* ³]©w§¹¤~§âÀɦW§ï¹L¨Ó */ - - vmsg("½ä½L³]©w§¹¦¨"); - return FULLUPDATE; -} -#endif - -static int -cite_post(int ent, const fileheader_t * fhdr, const char *direct) -{ - char fpath[PATHLEN]; - char title[TTLEN + 1]; - - setbfile(fpath, currboard, fhdr->filename); - strlcpy(title, "¡º ", sizeof(title)); - strlcpy(title + 3, fhdr->title, TTLEN - 3); - title[TTLEN] = '\0'; - a_copyitem(fpath, title, 0, 1); - b_man(); - return FULLUPDATE; -} - -int -edit_title(int ent, fileheader_t * fhdr, const char *direct) -{ - char genbuf[200] = ""; - fileheader_t tmpfhdr = *fhdr; - int dirty = 0; - int allow = 0; - - // should we allow edit-title here? - if (currstat == RMAIL) - allow = 0; - else if (HasUserPerm(PERM_SYSOP)) - allow = 2; - else if (currmode & MODE_BOARD || - strcmp(cuser.userid, fhdr->owner) == 0) - allow = 1; - - if (!allow) - return DONOTHING; - - if (fhdr && fhdr->title[0]) - strlcpy(genbuf, fhdr->title, TTLEN+1); - - if (getdata_buf(b_lines - 1, 0, "¼ÐÃD¡G", genbuf, TTLEN, DOECHO)) { - strlcpy(tmpfhdr.title, genbuf, sizeof(tmpfhdr.title)); - dirty++; - } - - if (allow >= 2) - { - if (getdata(b_lines - 1, 0, "§@ªÌ¡G", genbuf, IDLEN + 2, DOECHO)) { - strlcpy(tmpfhdr.owner, genbuf, sizeof(tmpfhdr.owner)); - dirty++; - } - if (getdata(b_lines - 1, 0, "¤é´Á¡G", genbuf, 6, DOECHO)) { - snprintf(tmpfhdr.date, sizeof(tmpfhdr.date), "%.5s", genbuf); - dirty++; - } - } - - if (dirty) - { - getdata(b_lines - 1, 0, "½T©w(Y/N)?[n] ", genbuf, 3, DOECHO); - if ((genbuf[0] == 'y' || genbuf[0] == 'Y') && dirty) { - // TODO verify if record is still valid - fileheader_t curr; - memset(&curr, 0, sizeof(curr)); - if (get_record(direct, &curr, sizeof(curr), ent) < 0 || - strcmp(curr.filename, fhdr->filename) != 0) - { - // modified... - vmsg("©êºp¡A¨t²Î¦£¸L¤¤¡A½Ðµy«á¦A¸Õ¡C"); - return FULLUPDATE; - } - *fhdr = tmpfhdr; - substitute_ref_record(direct, fhdr, ent); - } - return FULLUPDATE; - } - return DONOTHING; -} - -static int -solve_post(int ent, fileheader_t * fhdr, const char *direct) -{ - if ((currmode & MODE_BOARD)) { - fhdr->filemode ^= FILE_SOLVED; - substitute_ref_record(direct, fhdr, ent); - check_locked(fhdr); - return PART_REDRAW; - } - return DONOTHING; -} - - -static int -recommend_cancel(int ent, fileheader_t * fhdr, const char *direct) -{ - char yn[5]; - if (!(currmode & MODE_BOARD)) - return DONOTHING; - getdata(b_lines - 1, 0, "½T©wn±ÀÂËÂk¹s[y/N]? ", yn, 5, LCECHO); - if (yn[0] != 'y') - return FULLUPDATE; -#ifdef ASSESS - // to save resource - if (fhdr->recommend > 9) - { - inc_goodpost(fhdr->owner, -1 * (fhdr->recommend / 10)); - sendalert(fhdr->owner, ALERT_PWD_GOODPOST); - } -#endif - fhdr->recommend = 0; - - substitute_ref_record(direct, fhdr, ent); - return FULLUPDATE; -} - -static int -do_add_recommend(const char *direct, fileheader_t *fhdr, - int ent, const char *buf, int type) -{ - char path[PATHLEN]; - int update = 0; - /* - race here: - ¬°¤F´î¤Ö system calls , ²{¦bª½±µ¥Î·í«eªº±À¤å¼Æ +1 ¼g¤J .DIR ¤¤. - ³y¦¨ - 1.Y¸Ó¤åÀɦW³Q´«±¼ªº¸Ü, ±À¤å±N¼g¦ÜÂÂÀɦW¤¤ (³y¦¨«ÕÆFÀÉ) - 2.¨S¦³«·sŪ¤@¦¸, ©Ò¥H±À¤å¼Æ¥i¯à³Q¤Öºâ - 3.Y±Àªº®ÉÔ«e¤å³Q§R, ±N¥[¨ì«á¤åªº±À¤å¼Æ - - */ - setdirpath(path, direct, fhdr->filename); - if( log_file(path, 0, buf) == -1 ){ // ¤£ CREATE - vmsg("±ÀÂË/Äv¼Ð¥¢±Ñ"); - return -1; - } - - // XXX do lock some day! - - /* This is a solution to avoid most racing (still some), but cost four - * system calls. */ - - if(type == 0 && fhdr->recommend < MAX_RECOMMENDS ) - update = 1; - else if(type == 1 && fhdr->recommend > -MAX_RECOMMENDS) - update = -1; - fhdr->recommend += update; - - // since we want to do 'modification'... - fhdr->modified = dasht(path); - - if (fhdr->modified > 0) - { - if (modify_dir_lite(direct, ent, fhdr->filename, - fhdr->modified, NULL, update) < 0) - return -1; - // mark my self as "read this file". - brc_addlist(fhdr->filename, fhdr->modified); - } - - return 0; -} - -static int -do_bid(int ent, fileheader_t * fhdr, const boardheader_t *bp, - const char *direct, const struct tm *ptime) -{ - char genbuf[200], fpath[PATHLEN],say[30],*money; - bid_t bidinfo; - int mymax, next; - - setdirpath(fpath, direct, fhdr->filename); - strcat(fpath, ".bid"); - memset(&bidinfo, 0, sizeof(bidinfo)); - if (get_record(fpath, &bidinfo, sizeof(bidinfo), 1) < 0) - { - vmsg("¨t²Î¿ù»~: Äv¼Ð¸ê°T¤w¿ò¥¢¡A½Ð«¶}·s¼Ð¡C"); - return FULLUPDATE; - } - - move(18,0); - clrtobot(); - prints("Äv¼Ð¥DÃD: %s\n", fhdr->title); - print_bidinfo(0, bidinfo); - money = bidinfo.payby ? " NT$ " : MONEYNAME "$ "; - if( now > bidinfo.enddate || bidinfo.high == bidinfo.buyitnow ){ - outs("¦¹Äv¼Ð¤w¸gµ²§ô,"); - if( bidinfo.userid[0] ) { - /*if(!payby && bidinfo.usermax!=-1) - {¥HPtt¹ô¦Û°Ê¦©´Ú - }*/ - prints("®¥³ß %s ¥H %d ±o¼Ð!", bidinfo.userid, bidinfo.high); -#ifdef ASSESS - if (!(bidinfo.flag & SALE_COMMENTED) && strcmp(bidinfo.userid, currutmp->userid) == 0){ - char tmp = getans("±z¹ï©ó³o¦¸¥æ©öªºµû»ù¦p¦ó? 1:¨Î 2:¤í¨Î 3:´¶³q[Q]"); - if ('1' <= tmp && tmp <= '3'){ - switch(tmp){ - case 1: - inc_goodsale(bidinfo.userid, 1); - break; - case 2: - inc_badsale(bidinfo.userid, 1); - break; - } - bidinfo.flag |= SALE_COMMENTED; - - substitute_record(fpath, &bidinfo, sizeof(bidinfo), 1); - } - } -#endif - } - else outs("µL¤H±o¼Ð!"); - pressanykey(); - return FULLUPDATE; - } - - if( bidinfo.userid[0] ){ - prints("¤U¦¸¥X»ù¦Ü¤Ön:%s%d", money,bidinfo.high + bidinfo.increment); - if( bidinfo.buyitnow ) - prints(" (¿é¤J %d µ¥©ó¥Hª½±µÁʶRµ²§ô)",bidinfo.buyitnow); - next = bidinfo.high + bidinfo.increment; - } - else{ - prints("°_¼Ð»ù: %d", bidinfo.high); - next=bidinfo.high; - } - if( !strcmp(cuser.userid,bidinfo.userid) ){ - outs("§A¬O³Ì°ª±o¼ÐªÌ!"); - pressanykey(); - return FULLUPDATE; - } - if( strcmp(cuser.userid, fhdr->owner) == 0 ){ - vmsg("ĵ§i! ¥»¤H¤£¯à¥X»ù!"); - getdata_str(23, 0, "¬O§_n´£¦µ²¼Ð? (y/N)", genbuf, 3, LCECHO,"n"); - if( genbuf[0] != 'y' ) - return FULLUPDATE; - snprintf(genbuf, sizeof(genbuf), - ANSI_COLOR(1;31) "¡÷ " - ANSI_COLOR(33) "½æ¤è%s´£¦µ²¼Ð" - ANSI_RESET "%*s" - "¼Ð%15s %02d/%02d\n", - cuser.userid, (int)(45 - strlen(cuser.userid) - strlen(money)), - " ", fromhost, ptime->tm_mon + 1, ptime->tm_mday); - do_add_recommend(direct, fhdr, ent, genbuf, 0); - bidinfo.enddate = now; - substitute_record(fpath, &bidinfo, sizeof(bidinfo), 1); - vmsg("´£¦µ²¼Ð§¹¦¨"); - return FULLUPDATE; - } - getdata_str(23, 0, "¬O§_n¤U¼Ð? (y/N)", genbuf, 3, LCECHO,"n"); - if( genbuf[0] != 'y' ) - return FULLUPDATE; - - getdata(23, 0, "±zªº³Ì°ª¤U¼Ðª÷ÃB(0:¨ú®ø):", genbuf, 10, LCECHO); - mymax = atoi(genbuf); - if( mymax <= 0 ){ - vmsg("¨ú®ø¤U¼Ð"); - return FULLUPDATE; - } - - getdata(23,0,"¤U¼Ð·P¨¥:",say,12,DOECHO); - get_record(fpath, &bidinfo, sizeof(bidinfo), 1); - - if( bidinfo.buyitnow && mymax > bidinfo.buyitnow ) - mymax = bidinfo.buyitnow; - else if( !bidinfo.userid[0] ) - next = bidinfo.high; - else - next = bidinfo.high + bidinfo.increment; - - if( mymax< next || (bidinfo.payby == 0 && cuser.money < mymax) ){ - vmsg("¼Ðª÷¤£¨¬·m¼Ð"); - return FULLUPDATE; - } - - snprintf(genbuf, sizeof(genbuf), - ANSI_COLOR(1;31) "¡÷ " ANSI_COLOR(33) "%s" ANSI_RESET ANSI_COLOR(33) ":%s" ANSI_RESET "%*s" - "%s%-15d¼Ð%15s %02d/%02d\n", - cuser.userid, say, - (int)(31 - strlen(cuser.userid) - strlen(say)), " ", - money, - next, fromhost, - ptime->tm_mon + 1, ptime->tm_mday); - do_add_recommend(direct, fhdr, ent, genbuf, 0); - if( next > bidinfo.usermax ){ - bidinfo.usermax = mymax; - bidinfo.high = next; - strcpy(bidinfo.userid, cuser.userid); - } - else if( mymax > bidinfo.usermax ) { - bidinfo.high = bidinfo.usermax + bidinfo.increment; - if( bidinfo.high > mymax ) - bidinfo.high = mymax; - bidinfo.usermax = mymax; - strcpy(bidinfo.userid, cuser.userid); - - snprintf(genbuf, sizeof(genbuf), - ANSI_COLOR(1;31) "¡÷ " ANSI_COLOR(33) "¦Û°ÊÄv¼Ð%s³Ó¥X" ANSI_RESET - ANSI_COLOR(33) ANSI_RESET "%*s%s%-15d¼Ð %02d/%02d\n", - cuser.userid, - (int)(20 - strlen(cuser.userid)), " ", money, - bidinfo.high, - ptime->tm_mon + 1, ptime->tm_mday); - do_add_recommend(direct, fhdr, ent, genbuf, 0); - } - else { - if( mymax + bidinfo.increment < bidinfo.usermax ) - bidinfo.high = mymax + bidinfo.increment; - else - bidinfo.high=bidinfo.usermax; /*³oÃä©Ç©Çªº*/ - snprintf(genbuf, sizeof(genbuf), - ANSI_COLOR(1;31) "¡÷ " ANSI_COLOR(33) "¦Û°ÊÄv¼Ð%s³Ó¥X" - ANSI_RESET ANSI_COLOR(33) ANSI_RESET "%*s%s%-15d¼Ð %02d/%02d\n", - bidinfo.userid, - (int)(20 - strlen(bidinfo.userid)), " ", money, - bidinfo.high, - ptime->tm_mon + 1, ptime->tm_mday); - do_add_recommend(direct, fhdr, ent, genbuf, 0); - } - substitute_record(fpath, &bidinfo, sizeof(bidinfo), 1); - vmsg("®¥³ß±z! ¥H³Ì°ª»ù·m¼Ð§¹¦¨!"); - return FULLUPDATE; -} - -static int -recommend(int ent, fileheader_t * fhdr, const char *direct) -{ - struct tm *ptime = localtime4(&now); - char buf[PATHLEN], msg[STRLEN]; -#ifndef OLDRECOMMEND - static const char *ctype[3] = { - "±À", "¼N", "¡÷" - }; - static const char *ctype_attr[3] = { - ANSI_COLOR(1;33), - ANSI_COLOR(1;31), - ANSI_COLOR(1;37), - }, *ctype_attr2[3] = { - ANSI_COLOR(1;37), - ANSI_COLOR(1;31), - ANSI_COLOR(1;31), - }, *ctype_long[3] = { - "ȱo±ÀÂË", - "µ¹¥¦¼NÁn", - "¥u¥[¡÷µù¸Ñ" - }; -#endif - int type, maxlength; - boardheader_t *bp; - static time4_t lastrecommend = 0; - static int lastrecommend_bid = -1; - static char lastrecommend_fname[FNLEN] = ""; - int isGuest = (strcmp(cuser.userid, STR_GUEST) == EQUSTR); - int logIP = 0; - int ymsg = b_lines -1; -#ifdef ASSESS - char oldrecom = fhdr->recommend; -#endif // ASSESS - - if (!fhdr || !fhdr->filename[0]) - return DONOTHING; - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - if (bp->brdattr & BRD_NORECOMMEND || fhdr->filename[0] == 'L' || - ((fhdr->filemode & FILE_MARKED) && (fhdr->filemode & FILE_SOLVED))) { - vmsg("©êºp, ¸T¤î±ÀÂË©ÎÄv¼Ð"); - return FULLUPDATE; - } - - if ( !CheckPostPerm() || - bp->brdattr & BRD_VOTEBOARD || -#ifndef GUESTRECOMMEND - isGuest || -#endif - fhdr->filemode & FILE_VOTE) { - vmsg("±zÅv¤£¨¬, µLªk±ÀÂË!"); // "(¥i«ö¤j¼g I ¬d¬Ý¨î)" - return FULLUPDATE; - } - -#ifdef SAFE_ARTICLE_DELETE - if (fhdr->filename[0] == '.') { - vmsg("¥»¤å¤w§R°£"); - return FULLUPDATE; - } -#endif - - if( fhdr->filemode & FILE_BID){ - return do_bid(ent, fhdr, bp, direct, ptime); - } - -#ifndef DEBUG - if (!CheckPostRestriction(currbid)) - { - vmsg("§A¤£°÷¸ê²`³á¡I (¥i«ö i ¬d¬Ý¨î)"); - return FULLUPDATE; - } -#endif - - if((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP)) - { - /* I'm BM or SYSOP. */ - } - else if (bp->brdattr & BRD_NOFASTRECMD) - { - int d = (int)bp->fastrecommend_pause - (now - lastrecommend); - if (d > 0) - { - vmsgf("¥»ªO¸T¤î§Ö³t³sÄò±À¤å¡A½Ð¦Aµ¥ %d ¬í", d); - return FULLUPDATE; - } - } - { - // kcwu - static unsigned char lastrecommend_minute = 0; - static unsigned short recommend_in_minute = 0; - unsigned char now_in_minute = (unsigned char)(now / 60); - if(now_in_minute != lastrecommend_minute) { - recommend_in_minute = 0; - lastrecommend_minute = now_in_minute; - } - recommend_in_minute++; - if(recommend_in_minute>60) { - vmsg("¨t²Î¸T¤îµu®É¶¡¤º¤j¶q±À¤å"); - return FULLUPDATE; - } - } - { - // kcwu - char path[PATHLEN]; - off_t size; - setdirpath(path, direct, fhdr->filename); - size = dashs(path); - if (size > 5*1024*1024) { - vmsg("ÀɮפӤj, µLªkÄ~Äò±À¤å, ½Ð¥t¼¶¤åµoªí"); - return FULLUPDATE; - } - - if (size > 100*1024) { - int d = 10 - (now - lastrecommend); - if (d > 0) { - vmsgf("¥»¤å¤w¹Lªø, ¸T¤î§Ö³t³sÄò±À¤å, ½Ð¦Aµ¥ %d ¬í", d); - return FULLUPDATE; - } - } - } - - -#ifdef USE_COOLDOWN - if(check_cooldown(bp)) - return FULLUPDATE; -#endif - - type = 0; - - // why "recommend == 0" here? - // some users are complaining that they like to fxck up system - // with lots of recommend one-line text. - // since we don't support recognizing update of recommends now, - // they tend to use the counter to identify whether an arcitle - // has new recommends or not. - // so, make them happy here. -#ifndef OLDRECOMMEND - // no matter it is first time or not. - if (strcmp(cuser.userid, fhdr->owner) == 0) -#else - // old format is one way counter, so let's relax. - if (fhdr->recommend == 0 && strcmp(cuser.userid, fhdr->owner) == 0) -#endif - { - // owner recommend - type = 2; - move(ymsg--, 0); clrtoeol(); -#ifndef OLDRECOMMEND - outs("§@ªÌ¥»¤H, ¨Ï¥Î ¡÷ ¥[µù¤è¦¡\n"); -#else - outs("§@ªÌ¥»¤Hº±À, ¨Ï¥Î ¡÷ ¥[µù¤è¦¡\n"); -#endif - - } -#ifndef DEBUG - else if (!(currmode & MODE_BOARD) && - (now - lastrecommend) < ( -#if 0 - /* i'm not sure whether this is better or not */ - (bp->brdattr & BRD_NOFASTRECMD) ? - bp->fastrecommend_pause : -#endif - 90)) - { - // too close - type = 2; - move(ymsg--, 0); clrtoeol(); - outs("®É¶¡¤Óªñ, ¨Ï¥Î ¡÷ ¥[µù¤è¦¡\n"); - } -#endif - -#ifndef OLDRECOMMEND - else if (!(bp->brdattr & BRD_NOBOO)) - { - /* most people use recommendation just for one-line reply. - * so we change default to (2)= comment only now. -#define RECOMMEND_DEFAULT_VALUE (2) - */ -#define RECOMMEND_DEFAULT_VALUE (0) /* current user behavior */ - - move(b_lines, 0); clrtoeol(); - outs(ANSI_COLOR(1) "±zı±o³o½g¤å³¹ "); - prints("%s1.%s %s2.%s %s3.%s " ANSI_RESET "[%d]? ", - ctype_attr[0], ctype_long[0], - ctype_attr[1], ctype_long[1], - ctype_attr[2], ctype_long[2], - RECOMMEND_DEFAULT_VALUE+1); - - // poor BBS term has problem positioning with ANSI. - move(b_lines, 55); - type = igetch() - '1'; - if(type < 0 || type > 2) - type = RECOMMEND_DEFAULT_VALUE; - move(b_lines, 0); clrtoeol(); - } -#endif - - // warn if article is outside post - if (strchr(fhdr->owner, '.') != NULL) - { - move(ymsg--, 0); clrtoeol(); - outs(ANSI_COLOR(1;31) - "¡»³o½g¤å³¹¨Ó¦Û¼Ê¦WªO©Î¥~¯¸Âà«HªO¡Aì§@ªÌ¥i¯àµLªk¬Ý¨ì±À¤å¡C" - ANSI_RESET "\n"); - } - - // warn if in non-standard mode - { - char *p = strrchr(direct, '/'); - // allow .DIR or .DIR.bottom - if (!p || strncmp(p+1, FN_DIR, strlen(FN_DIR)) != 0) - { - ymsg --; - move(ymsg--, 0); clrtoeol(); - outs(ANSI_COLOR(1;33) - "¡»±z¥¿¦b·j´M(¼ÐÃD¡B§@ªÌ...)©Î¨ä¥¦¯S®í¦Cªí¼Ò¦¡¡A" - "±À¤åp¼Æ»Pקï°O¿ý±N·|¤À¶}pºâ¡C" - ANSI_RESET "\n" - " Y·Q¥¿±`p¼Æ½Ð¥ý¥ªÁä°h¦^¥¿±`¦Cªí¼Ò¦¡¡C\n"); - } - } - - if(type > 2 || type < 0) - type = 0; - - maxlength = 78 - - 3 /* lead */ - - 6 /* date */ - - 1 /* space */ - - 6 /* time */; - - if (bp->brdattr & BRD_IPLOGRECMD || isGuest) - { - maxlength -= 15 /* IP */; - logIP = 1; - } - -#ifdef OLDRECOMMEND - maxlength -= 2; /* '±À' */ - maxlength -= strlen(cuser.userid); - sprintf(buf, "%s %s:", "¡÷" , cuser.userid); - -#else // !OLDRECOMMEND - maxlength -= strlen(cuser.userid); - sprintf(buf, "%s%s%s %s:", - ctype_attr[type], ctype[type], ANSI_RESET, - cuser.userid); -#endif // !OLDRECOMMEND - - move(b_lines, 0); - clrtoeol(); - - if (!getdata(b_lines, 0, buf, msg, maxlength, DOECHO)) - return FULLUPDATE; - - // make sure to do modification - { - char ans[3]; - sprintf(buf+strlen(buf), ANSI_COLOR(7) "%-*s" - ANSI_RESET " ½T©w[y/N]:", maxlength, msg); - if(!getdata(b_lines, 0, buf, ans, sizeof(ans), LCECHO) || - ans[0] != 'y') - return FULLUPDATE; - } - - // log if you want -#ifdef LOG_PUSH - { - static int tolog = 0; - if( tolog == 0 ) - tolog = - (cuser.numlogins < 50 || (now - cuser.firstlogin) < 86400 * 7) - ? 1 : 2; - if( tolog == 1 ){ - FILE *fp; - if( (fp = fopen("log/push", "a")) != NULL ){ - fprintf(fp, "%s %d %s %s %s\n", cuser.userid, now, currboard, fhdr->filename, msg); - fclose(fp); - } - sleep(1); - } - } -#endif // LOG_PUSH - - STATINC(STAT_RECOMMEND); - - { - /* build tail first. */ - char tail[STRLEN]; - - if(logIP) - { - snprintf(tail, sizeof(tail), - "%15s %02d/%02d %02d:%02d", - fromhost, - ptime->tm_mon+1, ptime->tm_mday, - ptime->tm_hour, ptime->tm_min); - } else { - snprintf(tail, sizeof(tail), - " %02d/%02d %02d:%02d", - ptime->tm_mon+1, ptime->tm_mday, - ptime->tm_hour, ptime->tm_min); - } - -#ifdef OLDRECOMMEND - snprintf(buf, sizeof(buf), - ANSI_COLOR(1;31) "¡÷ " ANSI_COLOR(33) "%s" - ANSI_RESET ANSI_COLOR(33) ":%-*s" ANSI_RESET - "±À%s\n", - cuser.userid, maxlength, msg, tail); -#else - snprintf(buf, sizeof(buf), - "%s%s " ANSI_COLOR(33) "%s" ANSI_RESET ANSI_COLOR(33) - ":%-*s" ANSI_RESET "%s\n", - ctype_attr2[type], ctype[type], cuser.userid, - maxlength, msg, tail); -#endif // OLDRECOMMEND - } - - do_add_recommend(direct, fhdr, ent, buf, type); - -#ifdef ASSESS - /* ¨C 10 ¦¸±À¤å ¥[¤@¦¸ goodpost */ - // TODO Âà¨Óªº«ç»ò¿ì¡H - // when recommend reaches MAX_RECOMMENDS... - if (type ==0 && (fhdr->filemode & FILE_MARKED) && - (fhdr->recommend != oldrecom) && - fhdr->recommend % 10 == 0) - { - inc_goodpost(fhdr->owner, 1); - sendalert(fhdr->owner, ALERT_PWD_GOODPOST); - } -#endif - - lastrecommend = now; - lastrecommend_bid = currbid; - strlcpy(lastrecommend_fname, fhdr->filename, sizeof(lastrecommend_fname)); - return FULLUPDATE; -} - -static int -mark_post(int ent, fileheader_t * fhdr, const char *direct) -{ - char buf[STRLEN], fpath[STRLEN]; - - if (!(currmode & MODE_BOARD)) - return DONOTHING; - - setbpath(fpath, currboard); - sprintf(buf, "%s/%s", fpath, fhdr->filename); - - if( !(fhdr->filemode & FILE_MARKED) && /* Y¥Ø«eÁÙ¨S¦³ mark ¤~n check */ - access(buf, F_OK) < 0 ) - return DONOTHING; - - fhdr->filemode ^= FILE_MARKED; - -#ifdef ASSESS - if (!(fhdr->filemode & FILE_BID)){ - if (fhdr->filemode & FILE_MARKED) { - if (!(currbrdattr & BRD_BAD) && fhdr->recommend >= 10) - { - inc_goodpost(fhdr->owner, fhdr->recommend / 10); - sendalert(fhdr->owner, ALERT_PWD_GOODPOST); - } - } - else if (fhdr->recommend > 9) - { - inc_goodpost(fhdr->owner, -1 * (fhdr->recommend / 10)); - sendalert(fhdr->owner, ALERT_PWD_GOODPOST); - } - } -#endif - - substitute_ref_record(direct, fhdr, ent); - check_locked(fhdr); - return PART_REDRAW; -} - -int -del_range(int ent, const fileheader_t *fhdr, const char *direct) -{ - char num1[8], num2[8]; - int inum1, inum2; - boardheader_t *bp = NULL; - - /* ¦³¤TºØ±¡ªp·|¶i³o¸Ì, «H¥ó, ¬ÝªO, ºëµØ°Ï */ - - if( direct[0] != 'h' && currbid) /* «H¥ó¤£¥Î check */ - { - // «Ü¤£©¯ªº¬O¦³¤@ºØ¬O«H¥ó->mail_cite->ºëµØ°Ï - bp = getbcache(currbid); - if (strcmp(bp->brdname, GLOBAL_SECURITY) == 0) - return DONOTHING; - } - - /* rocker.011018: ¦ê±µ¼Ò¦¡¤UÁÙ¬O¤£¤¹³\§R°£¤ñ¸û¦n */ - if (currmode & MODE_SELECT) { - vmsg("½Ð¥ý¦^¨ì¥¿±`¼Ò¦¡«á¦A¶i¦æ§R°£..."); - return FULLUPDATE; - } - - if ((currstat != READING) || (currmode & MODE_BOARD)) { - getdata(1, 0, "[³]©w§R°£½d³ò] °_ÂI¡G", num1, 6, DOECHO); - inum1 = atoi(num1); - if (inum1 <= 0) { - vmsg("°_ÂI¦³»~"); - return FULLUPDATE; - } - getdata(1, 28, "²×ÂI¡G", num2, 6, DOECHO); - inum2 = atoi(num2); - if (inum2 < inum1) { - vmsg("²×ÂI¦³»~"); - return FULLUPDATE; - } - getdata(1, 48, msg_sure_ny, num1, 3, LCECHO); - if (*num1 == 'y') { - outmsg("³B²z¤¤,½Ðµy«á..."); - refresh(); -#ifdef SAFE_ARTICLE_DELETE - if(bp && !(currmode & MODE_DIGEST) && bp->nuser > 30 ) - safe_article_delete_range(direct, inum1, inum2); - else - delete_range(direct, inum1, inum2); -#else - delete_range(direct, inum1, inum2); -#endif - fixkeep(direct, inum1); - - if ((curredit & EDIT_MAIL)==0 && (currmode & MODE_BOARD)) // Ptt:update cache - setbtotal(currbid); - else if(currstat == RMAIL) - setupmailusage(); - - return DIRCHANGED; - } - return FULLUPDATE; - } - return DONOTHING; -} - -static int -del_post(int ent, fileheader_t * fhdr, char *direct) -{ - char genbuf[100], newpath[PATHLEN]; - int not_owned, tusernum; - boardheader_t *bp; - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - - if (strcmp(bp->brdname, GLOBAL_SECURITY) == 0) - return DONOTHING; - - /* TODO recursive lookup */ - if (currmode & MODE_SELECT) { - vmsg("½Ð¦^¨ì¤@¯ë¼Ò¦¡¦A§R°£¤å³¹"); - return DONOTHING; - } - - if ((fhdr->filemode & FILE_BOTTOM) || - (fhdr->filemode & FILE_MARKED) || (fhdr->filemode & FILE_DIGEST) || - (fhdr->owner[0] == '-')) - return DONOTHING; - - if(fhdr->filemode & FILE_ANONYMOUS) - /* When the file is anonymous posted, fhdr->multi.anon_uid is author. - * see do_general() */ - tusernum = fhdr->multi.anon_uid; - else - tusernum = searchuser(fhdr->owner, NULL); - - not_owned = (tusernum == usernum ? 0: 1); - if ((!(currmode & MODE_BOARD) && not_owned) || - ((bp->brdattr & BRD_VOTEBOARD) && !HasUserPerm(PERM_SYSOP)) || - !strcmp(cuser.userid, STR_GUEST)) - return DONOTHING; - - if (fhdr->filename[0]=='L') fhdr->filename[0]='M'; - - getdata(1, 0, msg_del_ny, genbuf, 3, LCECHO); - if (genbuf[0] == 'y') { - if( -#ifdef SAFE_ARTICLE_DELETE - (bp->nuser > 30 && !(currmode & MODE_DIGEST) && - !safe_article_delete(ent, fhdr, direct)) || -#endif - !delete_record(direct, sizeof(fileheader_t), ent) - ) { - - cancelpost(fhdr, not_owned, newpath); - deleteCrossPost(fhdr, bp->brdname); -#ifdef ASSESS -#define SIZE sizeof(badpost_reason) / sizeof(char *) - - // TODO not_owned ®É¤]n§ïÅÜ numpost? - if (not_owned && tusernum > 0 && !(currmode & MODE_DIGEST)) { - if (now - atoi(fhdr->filename + 2) > 7 * 24 * 60 * 60) - /* post older than a week */ - genbuf[0] = 'n'; - else - getdata(1, 40, "´c¦H¤å³¹?(y/N)", genbuf, 3, LCECHO); - - if (genbuf[0]=='y') { - int i; - char *userid=getuserid(tusernum); - int rpt_bid; - - move(b_lines - 2, 0); - clrtobot(); - for (i = 0; i < SIZE; i++) - prints("%d.%s ", i + 1, badpost_reason[i]); - prints("%d.%s", i + 1, "¨ä¥L"); - getdata(b_lines - 1, 0, "½Ð¿ï¾Ü[0:¨ú®ø¦H¤å]:", genbuf, 3, LCECHO); - i = genbuf[0] - '1'; - if (i >= 0 && i < SIZE) - sprintf(genbuf,"¦H¤å°h¦^(%s)", badpost_reason[i]); - else if(i==SIZE) - { - strcpy(genbuf,"¦H¤å°h¦^("); - getdata_buf(b_lines, 0, "½Ð¿é¤Jì¦]", genbuf+9, - 50, DOECHO); - strcat(genbuf,")"); - } - if(i>=0 && i <= SIZE) - { - strncat(genbuf, fhdr->title, 64-strlen(genbuf)); - -#ifdef USE_COOLDOWN - add_cooldowntime(tusernum, 60); - add_posttimes(tusernum, 15); //Ptt: áµ² post for 1 hour -#endif - - if (!(inc_badpost(userid, 1) % 5)){ - userec_t xuser; - post_violatelaw(userid, BBSMNAME " ¨t²Îĵ¹î", - "¦H¤å²Öp 5 ½g", "»@³æ¤@±i"); - mail_violatelaw(userid, BBSMNAME " ¨t²Îĵ¹î", - "¦H¤å²Öp 5 ½g", "»@³æ¤@±i"); - kick_all(userid); - passwd_query(tusernum, &xuser); - xuser.money = moneyof(tusernum); - xuser.vl_count++; - xuser.userlevel |= PERM_VIOLATELAW; - xuser.timeviolatelaw = now; - passwd_update(tusernum, &xuser); - } - sendalert(userid, ALERT_PWD_BADPOST); - mail_id(userid, genbuf, newpath, cuser.userid); - -#ifdef BAD_POST_RECORD - rpt_bid = getbnum(BAD_POST_RECORD); - if (rpt_bid > 0) { - fileheader_t report_fh; - char report_path[PATHLEN]; - - setbpath(report_path, BAD_POST_RECORD); - stampfile(report_path, &report_fh); - - strcpy(report_fh.owner, "[" BBSMNAME "ĵ¹î§½]"); - snprintf(report_fh.title, sizeof(report_fh.title), - "%s ªO %s ªO¥Dµ¹¤© %s ¤@½g¦H¤å", - currboard, cuser.userid, userid); - Copy(newpath, report_path); - - setbdir(report_path, BAD_POST_RECORD); - append_record(report_path, &report_fh, sizeof(report_fh)); - - touchbtotal(rpt_bid); - } -#endif /* defined(BAD_POST_RECORD) */ - } - } - } -#undef SIZE -#endif - - setbtotal(currbid); - if (fhdr->multi.money < 0 || fhdr->filemode & FILE_ANONYMOUS) - fhdr->multi.money = 0; - if (not_owned && tusernum && fhdr->multi.money > 0 && - !IsFreeBoardName(currboard)) - { - deumoney(tusernum, -fhdr->multi.money); -#ifdef USE_COOLDOWN - if (bp->brdattr & BRD_COOLDOWN) - add_cooldowntime(tusernum, 15); -#endif - } - - // owner case. - - if (!not_owned && !IsFreeBoardName(currboard)) { - - // digest ¤£¥ÎºÞ - // new rule: only articles with money need updating - // numpost (to solve deleting cross-posts). - if (!(currmode & MODE_DIGEST) && (fhdr->multi.money > 0)) - { - if (cuser.numposts) - cuser.numposts--; - demoney(-fhdr->multi.money); - - vmsgf("±zªº¤å³¹´î¬° %d ½g¡A¤ä¥I²M¼ä¶O %d »È", - cuser.numposts, fhdr->multi.money); - } - } - return DIRCHANGED; - } // delete_record - } // genbuf[0] == 'y' - return FULLUPDATE; -} - -static int // Ptt: ×¥ÛÀY¤å -show_filename(int ent, const fileheader_t * fhdr, const char *direct) -{ - if(!HasUserPerm(PERM_SYSOP)) return DONOTHING; - vmsgf("ÀɮצWºÙ: %s ", fhdr->filename); - return PART_REDRAW; -} - -static int -lock_post(int ent, fileheader_t * fhdr, const char *direct) -{ - char fn1[MAXPATHLEN]; - char genbuf[256] = {'\0'}; - int i; - boardheader_t *bp = NULL; - - if (currstat == RMAIL) - return DONOTHING; - - if (!(currmode & MODE_BOARD) && !HasUserPerm(PERM_SYSOP | PERM_POLICE)) - return DONOTHING; - - bp = getbcache(currbid); - assert(bp); - - if (fhdr->filename[0]=='M') { - if (!HasUserPerm(PERM_SYSOP | PERM_POLICE)) - return DONOTHING; - - getdata(b_lines - 1, 0, "½Ð¿é¤JÂê©w²z¥Ñ¡G", genbuf, 50, DOECHO); - - if (getans("n±N¤å³¹Âê©w¶Ü(y/N)?") != 'y') - return FULLUPDATE; - setbfile(fn1, currboard, fhdr->filename); - fhdr->filename[0] = 'L'; - syncnow(); - bp->SRexpire = now; - } - else if (fhdr->filename[0]=='L') { - if (getans("n±N¤å³¹Âê©w¸Ñ°£¶Ü(y/N)?") != 'y') - return FULLUPDATE; - fhdr->filename[0] = 'M'; - setbfile(fn1, currboard, fhdr->filename); - syncnow(); - bp->SRexpire = now; - } - substitute_ref_record(direct, fhdr, ent); - post_policelog(currboard, fhdr->title, "Âê¤å", genbuf, fhdr->filename[0] == 'L' ? 1 : 0); - if (fhdr->filename[0] == 'L') { - fhdr->filename[0] = 'M'; - do_crosspost("PoliceLog", fhdr, fn1, 0); - fhdr->filename[0] = 'L'; - snprintf(genbuf, sizeof(genbuf), "%s ªO¾DÂê©w¤å³¹ - %s", currboard, fhdr->title); - for (i = 0; i < MAX_BMs && SHM->BMcache[currbid-1][i] != -1; i++) - mail_id(SHM->userid[SHM->BMcache[currbid-1][i] - 1], genbuf, fn1, "[¨t²Î]"); - } - return FULLUPDATE; -} - -static int -view_postinfo(int ent, const fileheader_t * fhdr, const char *direct, int crs_ln) -{ - aidu_t aidu = 0; - int l = crs_ln + 3; /* line of cursor */ - int area_l = l + 1; - const int area_lines = 4; - - if(!fhdr || fhdr->filename[0] == '.' || !fhdr->filename[0]) - return DONOTHING; - - if((area_l + area_lines > b_lines) || /* ¤U±©ñ¤£¤U */ - (l >= (b_lines * 2 / 3))) /* ²¤¶W¹Lµe± 2/3 */ - area_l -= (area_lines + 1); - - grayout(0, MIN(l - 1, area_l)-1, GRAYOUT_DARK); - grayout(MAX(l + 1 + 1, area_l + area_lines), b_lines-1, GRAYOUT_DARK); - grayout(l, l, GRAYOUT_BOLD); - - /* ²M°£¤å³¹ªº«e¤@¦æ©Î«á¤@¦æ */ - if(area_l > l) - move(l - 1, 0); - else - move(l + 1, 0); - clrtoeol(); - - move(area_l-(area_l < l), 0); - clrtoln(area_l -(area_l < l) + area_lines+1); - outc(' '); outs(ANSI_CLRTOEND); - move(area_l -(area_l < l) + area_lines, 0); - outc(' '); outs(ANSI_CLRTOEND); - move(area_l, 0); - - prints("¢z¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢{\n"); - - aidu = fn2aidu((char *)fhdr->filename); - if(aidu > 0) - { - char aidc[10]; - int y, x; - - aidu2aidc(aidc, aidu); - prints("¢x " AID_DISPLAYNAME ": " - ANSI_COLOR(1) "#%s" ANSI_RESET " (%s) [%s] ", - aidc, currboard && currboard[0] ? currboard : "¥¼ª¾", - MYHOSTNAME); - getyx_ansi(&y, &x); - x = 75 - x; - if (x > 1) - prints("%.*s ", x, fhdr->title); - outs("\n"); - } - else - { - prints("¢x\n"); - } - - if(fhdr->filemode & FILE_ANONYMOUS) - /* When the file is anonymous posted, fhdr->multi.anon_uid is author. - * see do_general() */ - prints("¢x °Î¦WºÞ²z½s¸¹: %d (¦P¤@¤H¸¹½X·|¤@¼Ë)", - fhdr->multi.anon_uid + (int)currutmp->pid); - else { - int m = query_file_money(fhdr); - - if(m < 0) - prints("¢x ¯S®í¤å³¹¡AµL»ù®æ°O¿ý"); - else - prints("¢x ³o¤@½g¤å³¹È %d »È", m); - - } - prints("\n"); - prints("¢|¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢}\n"); - - /* ¦L¹ï¸Ü®Øªº¥kÃä¬É */ - { - int i; - - for(i = 1; i < area_lines - 1; i ++) - { - move_ansi(area_l + i , 76); - prints("¢x"); - } - } - { - int r = pressanykey(); - /* TODO: ¦h¥[¤@Ó LISTMODE_AID¡H */ - /* QQ: enable money listing mode */ - if (r == 'Q') - { - currlistmode = (currlistmode == LISTMODE_MONEY) ? - LISTMODE_DATE : LISTMODE_MONEY; - vmsg((currlistmode == LISTMODE_MONEY) ? - "¶}±Ò¤å³¹»ù®æ¦Cªí¼Ò¦¡" : "°±¤î¦C¥X¤å³¹»ù®æ"); - } - } - - return FULLUPDATE; -} - -#ifdef OUTJOBSPOOL -/* ¬ÝªO³Æ¥÷ */ -static int -tar_addqueue(void) -{ - char email[60], qfn[80], ans[2]; - FILE *fp; - char bakboard, bakman; - clear(); - showtitle("¬ÝªO³Æ¥÷", BBSNAME); - move(2, 0); - if (!((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP))) { - move(5, 10); - outs("©pn¬OªO¥D©Î¬O¯¸ªø¤~¯àÂæÂæ°Ú -.-\"\""); - pressanykey(); - return FULLUPDATE; - } - snprintf(qfn, sizeof(qfn), BBSHOME "/jobspool/tarqueue.%s", currboard); - if (access(qfn, 0) == 0) { - outs("¤w¸g±Æ©w¦æµ{, µy«á·|¶i¦æ³Æ¥÷"); - pressanykey(); - return FULLUPDATE; - } -#ifdef TARQUEUE_SENDURL - move (3,0); outs("½Ð¿é¤J³qª¾«H½c (¹w³]¬°¦¹ BBS ±b¸¹«H½c): "); - if (!getdata_str(4, 2, "", - email, sizeof(email), DOECHO, cuser.userid)) - return FULLUPDATE; - if (strstr(email, "@") == NULL) - { - strcat(email, ".bbs@"); - strcat(email, MYHOSTNAME); - } - move(4,0); clrtoeol(); - outs(email); -#else - if (!getdata(4, 0, "½Ð¿é¤J¥Øªº«H½c¡G", email, sizeof(email), DOECHO)) - return FULLUPDATE; - - /* check email -.-"" */ - if (strstr(email, "@") == NULL || strstr(email, ".bbs@") != NULL) { - move(6, 0); - outs("±z«ü©wªº«H½c¤£¥¿½T! "); - pressanykey(); - return FULLUPDATE; - } -#endif - getdata(6, 0, "n³Æ¥÷¬ÝªO¤º®e¶Ü(Y/N)?[Y]", ans, sizeof(ans), LCECHO); - bakboard = (ans[0] == 'n' || ans[0] == 'N') ? 0 : 1; - getdata(7, 0, "n³Æ¥÷ºëµØ°Ï¤º®e¶Ü(Y/N)?[N]", ans, sizeof(ans), LCECHO); - bakman = (ans[0] == 'y' || ans[0] == 'Y') ? 1 : 0; - if (!bakboard && !bakman) { - move(8, 0); - outs("¥i¬O§ÚÌ¥u¯à³Æ¥÷¬ÝªO©ÎºëµØ°ÏªºC ^^\"\"\""); - pressanykey(); - return FULLUPDATE; - } - fp = fopen(qfn, "w"); - fprintf(fp, "%s\n", cuser.userid); - fprintf(fp, "%s\n", email); - fprintf(fp, "%d,%d\n", bakboard, bakman); - fclose(fp); - - move(10, 0); - outs("¨t²Î¤w¸g±N±zªº³Æ¥÷±Æ¤J¦æµ{, \n"); - outs("µy«á±N·|¦b¨t²Ît²ü¸û§Cªº®ÉÔ±N¸ê®Æ±Hµ¹±z~ :) "); - pressanykey(); - return FULLUPDATE; -} -#endif - -/* ----------------------------------------------------- */ -/* ¬ÝªO³Æ§Ñ¿ý¡B¤åºK¡BºëµØ°Ï */ -/* ----------------------------------------------------- */ -int -b_note_edit_bname(int bid) -{ - char buf[PATHLEN]; - int aborted; - boardheader_t *fh = getbcache(bid); - assert(0<=bid-1 && bid-1<MAX_BOARD); - setbfile(buf, fh->brdname, fn_notes); - aborted = vedit(buf, NA, NULL); - if (aborted == -1) { - clear(); - outs(msg_cancel); - pressanykey(); - } else { - if (!getdata(2, 0, "³]©w¦³®Ä´Á¤Ñ¡H(n/Y)", buf, 3, LCECHO) - || buf[0] != 'n') - fh->bupdate = gettime(3, fh->bupdate ? fh->bupdate : now, - "¦³®Ä¤é´Á¦Ü"); - else - fh->bupdate = 0; - assert(0<=bid-1 && bid-1<MAX_BOARD); - substitute_record(fn_board, fh, sizeof(boardheader_t), bid); - } - return 0; -} - -static int -b_notes_edit(void) -{ - if (currmode & MODE_BOARD) { - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - b_note_edit_bname(currbid); - return FULLUPDATE; - } - return 0; -} - -static int -bh_title_edit(void) -{ - boardheader_t *bp; - - if (currmode & MODE_BOARD) { - char genbuf[BTLEN]; - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - move(1, 0); - clrtoeol(); - getdata_str(1, 0, "½Ð¿é¤J¬ÝªO·s¤¤¤å±Ôz:", genbuf, - BTLEN - 16, DOECHO, bp->title + 7); - - if (!genbuf[0]) - return 0; - strip_ansi(genbuf, genbuf, STRIP_ALL); - strlcpy(bp->title + 7, genbuf, sizeof(bp->title) - 7); - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); - log_usies("SetBoard", currboard); - return FULLUPDATE; - } - return 0; -} - -static int -b_notes(void) -{ - char buf[PATHLEN]; - int mr = 0; - - setbfile(buf, currboard, fn_notes); - mr = more(buf, NA); - - if (mr == -1) - { - clear(); - move(4, 20); - outs("¥»¬ÝªO©|µL¡u³Æ§Ñ¿ý¡v¡C"); - } - if(mr != READ_NEXT) - pressanykey(); - return FULLUPDATE; -} - -int -board_select(void) -{ - currmode &= ~MODE_SELECT; - currsrmode = 0; - if (currstat == RMAIL) - sethomedir(currdirect, cuser.userid); - else - setbdir(currdirect, currboard); - return NEWDIRECT; -} - -int -board_digest(void) -{ - if (currmode & MODE_SELECT) - board_select(); - currmode ^= MODE_DIGEST; - - // MODE_POST may be changed if board is modified. - // do not change post perm here. use other instead. - - setbdir(currdirect, currboard); - return NEWDIRECT; -} - - -static int -push_bottom(int ent, fileheader_t *fhdr, const char *direct) -{ - int num; - char buf[256]; - if ((currmode & MODE_DIGEST) || !(currmode & MODE_BOARD) - || fhdr->filename[0]=='L') - return DONOTHING; - setbottomtotal(currbid); // <- Ptt : will be remove when stable - num = getbottomtotal(currbid); - if( getans(fhdr->filemode & FILE_BOTTOM ? - "¨ú®ø¸m©³¤½§i?(y/N)": - "¥[¤J¸m©³¤½§i?(y/N)") != 'y' ) - return READ_REDRAW; - if(!(fhdr->filemode & FILE_BOTTOM) ){ - sprintf(buf, "%s.bottom", direct); - if(num >= 5){ - vmsg("¤£±o¶W¹L 5 ½g«n¤½§i ½Ðºë²!"); - return READ_REDRAW; - } - fhdr->filemode ^= FILE_BOTTOM; - fhdr->multi.refer.flag = 1; - fhdr->multi.refer.ref = ent; - append_record(buf, fhdr, sizeof(fileheader_t)); - } - else{ - fhdr->filemode ^= FILE_BOTTOM; - num = delete_record(direct, sizeof(fileheader_t), ent); - } - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - setbottomtotal(currbid); - return DIRCHANGED; -} - -static int -good_post(int ent, fileheader_t * fhdr, const char *direct) -{ - char genbuf[200]; - char genbuf2[200]; - int delta = 0; - - if ((currmode & MODE_DIGEST) || !(currmode & MODE_BOARD)) - return DONOTHING; - - if(getans(fhdr->filemode & FILE_DIGEST ? - "¨ú®ø¬ÝªO¤åºK?(Y/n)" : "¦¬¤J¬ÝªO¤åºK?(Y/n)") == 'n') - return READ_REDRAW; - - if (fhdr->filemode & FILE_DIGEST) { - fhdr->filemode = (fhdr->filemode & ~FILE_DIGEST); - if (!strcmp(currboard, GLOBAL_NOTE) || -#ifdef GLOBAL_ARTDSN - !strcmp(currboard, GLOBAL_ARTDSN) || -#endif - !strcmp(currboard, GLOBAL_BUGREPORT) || - !strcmp(currboard, GLOBAL_LAW) - ) - { - deumoney(searchuser(fhdr->owner, NULL), -1000); // TODO if searchuser() return 0 - if (!(currmode & MODE_SELECT)) - fhdr->multi.money -= 1000; - else - delta = -1000; - } - } else { - fileheader_t digest; - char *ptr, buf[PATHLEN]; - - memcpy(&digest, fhdr, sizeof(digest)); - digest.filename[0] = 'G'; - strlcpy(buf, direct, sizeof(buf)); - ptr = strrchr(buf, '/'); - assert(ptr); - ptr++; - ptr[0] = '\0'; - snprintf(genbuf, sizeof(genbuf), "%s%s", buf, digest.filename); - - if (dashf(genbuf)) - unlink(genbuf); - - digest.filemode = 0; - snprintf(genbuf2, sizeof(genbuf2), "%s%s", buf, fhdr->filename); - Copy(genbuf2, genbuf); - strcpy(ptr, fn_mandex); - append_record(buf, &digest, sizeof(digest)); - -#ifdef GLOBAL_DIGEST - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - if(!(getbcache(currbid)->brdattr & BRD_HIDE)) { - getdata(1, 0, "¦n¤åȱo¥Xª©¨ì¥þ¯¸¤åºK?(N/y)", genbuf2, 3, LCECHO); - if(genbuf2[0] == 'y') - do_crosspost(GLOBAL_DIGEST, &digest, genbuf, 1); - } -#endif - - fhdr->filemode = (fhdr->filemode & ~FILE_MARKED) | FILE_DIGEST; - if (!strcmp(currboard, GLOBAL_NOTE) || -#ifdef GLOBAL_ARTDSN - !strcmp(currboard, GLOBAL_ARTDSN) || -#endif - !strcmp(currboard, GLOBAL_BUGREPORT) || - !strcmp(currboard, GLOBAL_LAW) - ) - { - deumoney(searchuser(fhdr->owner, NULL), 1000); // TODO if searchuser() return 0 - if (!(currmode & MODE_SELECT)) - fhdr->multi.money += 1000; - else - delta = 1000; - } - } - substitute_ref_record(direct, fhdr, ent); - return FULLUPDATE; -} - -static int -b_help(void) -{ - show_helpfile(fn_boardhelp); - return FULLUPDATE; -} - -#ifdef USE_COOLDOWN - -int check_cooldown(boardheader_t *bp) -{ - int diff = cooldowntimeof(usernum) - now; - int i, limit[8] = {4000,1,2000,2,1000,3,-1,10}; - - if(diff<0) - SHM->cooldowntime[usernum - 1] &= 0xFFFFFFF0; - else if( !((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP))) - { - if( bp->brdattr & BRD_COOLDOWN ) - { - vmsgf("§NÀR¤@¤U§a¡I (¨î %d ¤À %d ¬í)", diff/60, diff%60); - return 1; - } - else if(posttimesof(usernum)==0xf) - { - vmsgf("¹ï¤£°_¡A±z³Q³]¦H¤å¡I (¨î %d ¤À %d ¬í)", diff/60, diff%60); - return 1; - } -#ifdef NO_WATER_POST - else - { - for(i=0; i<4; i++) - if(bp->nuser>limit[i*2] && posttimesof(usernum)>=limit[i*2+1]) - { - vmsgf("¹ï¤£°_¡A±zªº¤å³¹©Î±À¤å¶¡¹j¤ÓªñÅo¡I (¨î %d ¤À %d ¬í)", - diff/60, diff%60); - return 1; - } - } -#endif // NO_WATER_POST - } - return 0; -} -/** - * ³]©w¬ÝªO§NÀR¥\¯à, ¨î¨Ï¥ÎªÌµo¤å®É¶¡ - */ -static int -change_cooldown(void) -{ - char genbuf[256] = {'\0'}; - boardheader_t *bp = getbcache(currbid); - - if (!(HasUserPerm(PERM_SYSOP | PERM_POLICE) || - (HasUserPerm(PERM_SYSSUPERSUBOP) && GROUPOP()))) - return DONOTHING; - - if (bp->brdattr & BRD_COOLDOWN) { - if (getans("¥Ø«e°·Å¤¤, n¶}©ñ¶Ü(y/N)?") != 'y') - return FULLUPDATE; - bp->brdattr &= ~BRD_COOLDOWN; - outs("¤j®a³£¥i¥H post ¤å³¹¤F¡C\n"); - } else { - getdata(b_lines - 1, 0, "½Ð¿é¤J§NÀR²z¥Ñ¡G", genbuf, 50, DOECHO); - if (getans("n¨î post ÀW²v, °·Å¶Ü(y/N)?") != 'y') - return FULLUPDATE; - bp->brdattr |= BRD_COOLDOWN; - outs("¶}©l§NÀR¡C\n"); - } - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); - post_policelog(bp->brdname, NULL, "§NÀR", genbuf, bp->brdattr & BRD_COOLDOWN); - pressanykey(); - return FULLUPDATE; -} -#endif - -static int -b_moved_to_config() -{ - if ((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP)) - { - vmsg("³oÓ¥\\¯à¤w²¾¤J¬ÝªO³]©w (i) ¥h¤F¡I"); - return FULLUPDATE; - } - return DONOTHING; -} - -/* ----------------------------------------------------- */ -/* ¬ÝªO¥\¯àªí */ -/* ----------------------------------------------------- */ -/* onekey_size was defined in ../include/pttstruct.h, as ((int)'z') */ -const onekey_t read_comms[] = { - { 1, show_filename }, // Ctrl('A') - { 0, NULL }, // Ctrl('B') - { 0, NULL }, // Ctrl('C') - { 0, NULL }, // Ctrl('D') - { 1, lock_post }, // Ctrl('E') - { 0, NULL }, // Ctrl('F') -#ifdef NO_GAMBLE - { 0, NULL }, // Ctrl('G') -#else - { 0, hold_gamble }, // Ctrl('G') -#endif - { 0, NULL }, // Ctrl('H') - { 0, board_digest }, // Ctrl('I') KEY_TAB 9 - { 0, NULL }, // Ctrl('J') - { 0, NULL }, // Ctrl('K') - { 0, NULL }, // Ctrl('L') - { 0, NULL }, // Ctrl('M') - { 0, NULL }, // Ctrl('N') - { 0, do_post_openbid }, // Ctrl('O') // BETTER NOT USE ^O - UNIX not work - { 0, do_post }, // Ctrl('P') - { 0, NULL }, // Ctrl('Q') - { 0, NULL }, // Ctrl('R') - { 0, NULL }, // Ctrl('S') - { 0, NULL }, // Ctrl('T') - { 0, NULL }, // Ctrl('U') - { 0, do_post_vote }, // Ctrl('V') - { 0, whereami }, // Ctrl('W') - { 0, NULL }, // Ctrl('X') - { 0, NULL }, // Ctrl('Y') - { 1, push_bottom }, // Ctrl('Z') 26 - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 1, recommend }, // '%' (m3itoc style) - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, // 'A' 65 - { 0, bh_title_edit }, // 'B' - { 1, do_limitedit }, // 'C' - { 1, del_range }, // 'D' - { 1, edit_post }, // 'E' - { 0, NULL }, // 'F' - { 0, NULL }, // 'G' - { 0, b_moved_to_config }, // 'H' - { 0, b_config }, // 'I' -#ifdef USE_COOLDOWN - { 0, change_cooldown }, // 'J' -#else - { 0, NULL }, // 'J' -#endif - { 0, b_moved_to_config }, // 'K' - { 1, solve_post }, // 'L' - { 0, b_moved_to_config }, // 'M' - { 0, NULL }, // 'N' - { 0, NULL }, // 'O' - { 0, NULL }, // 'P' - { 1, view_postinfo }, // 'Q' - { 0, b_results }, // 'R' - { 0, NULL }, // 'S' - { 1, edit_title }, // 'T' - { 0, NULL }, // 'U' - { 0, b_vote }, // 'V' - { 0, b_notes_edit }, // 'W' - { 1, recommend }, // 'X' - { 1, recommend_cancel }, // 'Y' - { 0, NULL }, // 'Z' 90 - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, // 'a' 97 - { 0, b_notes }, // 'b' - { 1, cite_post }, // 'c' - { 1, del_post }, // 'd' - { 0, NULL }, // 'e' -#ifdef NO_GAMBLE - { 0, NULL }, // 'f' -#else - { 0, join_gamble }, // 'f' -#endif - { 1, good_post }, // 'g' - { 0, b_help }, // 'h' - { 0, b_config }, // 'i' - { 0, NULL }, // 'j' - { 0, NULL }, // 'k' - { 0, NULL }, // 'l' - { 1, mark_post }, // 'm' - { 0, NULL }, // 'n' - { 0, NULL }, // 'o' - { 0, NULL }, // 'p' - { 0, NULL }, // 'q' - { 1, read_post }, // 'r' - { 0, do_select }, // 's' - { 0, NULL }, // 't' -#ifdef OUTJOBSPOOL - { 0, tar_addqueue }, // 'u' -#else - { 0, NULL }, // 'u' -#endif - { 0, b_moved_to_config }, // 'v' - { 1, b_call_in }, // 'w' - { 1, cross_post }, // 'x' - { 1, reply_post }, // 'y' - { 0, b_man }, // 'z' 122 -}; - -int -Read(void) -{ - int mode0 = currutmp->mode; - int stat0 = currstat, tmpbid = currutmp->brc_id; - static int lastbid = -1; - char buf[PATHLEN]; -#ifdef LOG_BOARD - time4_t usetime = now; -#endif - - const char *bname = currboard[0] ? currboard : DEFAULT_BOARD; - if (enter_board(bname) < 0) - return 0; - - setutmpmode(READING); - - if (currbid != lastbid && - board_note_time && board_visit_time < *board_note_time) { - int mr; - - setbfile(buf, currboard, fn_notes); - mr = more(buf, NA); - if(mr == -1) - *board_note_time=0; - else if (mr != READ_NEXT) - pressanykey(); - } - lastbid = currbid; - i_read(READING, currdirect, readtitle, readdoent, read_comms, - currbid); - currmode &= ~MODE_POSTCHECKED; -#ifdef LOG_BOARD - log_board(currboard, now - usetime); -#endif - brc_update(); - setutmpbid(tmpbid); - currutmp->mode = mode0; - currstat = stat0; - return 0; -} - -void -ReadSelect(void) -{ - int mode0 = currutmp->mode; - int stat0 = currstat; - - currstat = SELECT; - if (do_select() == NEWDIRECT) - Read(); - setutmpbid(0); - currutmp->mode = mode0; - currstat = stat0; -} - -#ifdef LOG_BOARD -static void -log_board(iconst char *mode, time4_t usetime) -{ - if (usetime > 30) { - log_file(FN_USEBOARD, LOG_CREAT | LOG_VF, - "USE %-20.20s Stay: %5ld (%s) %s\n", - mode, usetime, cuser.userid, ctime4(&now)); - } -} -#endif - -int -Select(void) -{ - return do_select(); -} - -#ifdef HAVEMOBILE -void -mobile_message(const char *mobile, char *message) -{ - bsmtp(fpath, title, rcpt); -} -#endif diff --git a/mbbsd/bbslua.c b/mbbsd/bbslua.c deleted file mode 100644 index 0305bd78..00000000 --- a/mbbsd/bbslua.c +++ /dev/null @@ -1,1801 +0,0 @@ -////////////////////////////////////////////////////////////////////////// -// BBS-Lua Project -// -// Author: Hung-Te Lin(piaip), Jan. 2008. -// <piaip@csie.ntu.edu.tw> -// Create: 2008-01-04 22:02:58 -// $Id$ -// -// This source is released in MIT License, same as Lua 5.0 -// http://www.lua.org/license.html -// -// Copyright 2008 Hung-Te Lin <piaip@csie.ntu.edu.tw> -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -// TODO: -// BBSLUA 1.0 -// 1. add quick key/val conversion [deprecated] -// 2. add key values (UP/DOWN/...) [done] -// 3. remove i/o libraries [done] -// 4. add system break key (Ctrl-C) [done] -// 5. add version string and script tags [done] -// 6. standalone w32 sdk [done] -// 7. syntax highlight in editor [done] -// 8. prevent loadfile, dofile [done] -// 9. provide local storage -// ?. modify bbs user data (eg, money) -// ?. os.date(), os.exit(), abort(), os.time() -// ?. memory free issue in C library level? -// ?. add digital signature -// -// BBSLUA 2.0 -// 1. 2 people communication -// -// BBSLUA 3.0 -// 1. n people communication -////////////////////////////////////////////////////////////////////////// - -#include "bbs.h" -#include "fnv_hash.h" - -#include <lua.h> -#include <lualib.h> -#include <lauxlib.h> - -////////////////////////////////////////////////////////////////////////// -// CONST DEFINITION -////////////////////////////////////////////////////////////////////////// - -#define BBSLUA_INTERFACE_VER 0.119 // (0.201) -#define BBSLUA_SIGNATURE "--#BBSLUA" - -// BBS-Lua script format: -// $BBSLUA_SIGNATURE -// -- Interface: $interface -// -- Title: $title -// -- Notes: $notes -// -- Author: $author <email@domain> -// -- Version: $version -// -- Date: $date -// -- LatestRef: #AID board -// [... script ...] -// $BBSLUA_SIGNATURE - -////////////////////////////////////////////////////////////////////////// -// CONFIGURATION VARIABLES -////////////////////////////////////////////////////////////////////////// -#define BLAPI_PROTO int - -#define BLCONF_BREAK_KEY Ctrl('C') -#define BLCONF_EXEC_COUNT (5000) -#define BLCONF_PEEK_TIME (0.01) -#define BLCONF_KBHIT_TMIN (BLCONF_PEEK_TIME) -#define BLCONF_KBHIT_TMAX (60*10) -#define BLCONF_SLEEP_TMIN (BLCONF_PEEK_TIME) -#define BLCONF_SLEEP_TMAX (BLCONF_KBHIT_TMAX) -#define BLCONF_U_SECOND (1000000L) -#define BLCONF_PRINT_TOC_INDEX (2) - -#define BLCONF_MMAP_ATTACH -#define BLCONF_CURRENT_USERID cuser.userid -#define BLCONF_CURRENT_USERNICK cuser.nickname - -// BBS-Lua Storage -enum { - BLS_INVALID= 0, - BLS_GLOBAL = 1, - BLS_USER, -}; - -// #define BLSCONF_ENABLED -#define BLSCONF_GLOBAL_VAL "global" -#define BLSCONF_USER_VAL "user" -#define BLSCONF_GMAXSIZE (16*1024) // should be aligned to block size -#define BLSCONF_UMAXSIZE (16*1024) // should be aligned to block size -#define BLSCONF_GPATH BBSHOME "/luastore" -#define BLSCONF_UPATH ".luastore" -#define BLSCONF_PREFIX "v1_" -#define BLSCONF_MAXIO 32 // prevent bursting system - -// #define BBSLUA_USAGE - -#ifdef _WIN32 -# undef BLCONF_MMAP_ATTACH -# undef BLCONF_CURRENT_USERID -# define BLCONF_CURRENT_USERID "guest" -# undef BLCONF_CURRENT_USERNICK -# define BLCONF_CURRENT_USERNICK "´ú¸Õ±b¸¹" -#endif - -////////////////////////////////////////////////////////////////////////// -// GLOBAL VARIABLES -////////////////////////////////////////////////////////////////////////// -typedef struct { - char running; // prevent re-entrant - char abort; // system break key hit - char iocounter; // prevent bursting i/o - Fnv32_t storename; // storage filename -} BBSLuaRT; - -// runtime information -// static -BBSLuaRT blrt = {0}; - -#define BL_INIT_RUNTIME() { \ - memset(&blrt, 0, sizeof(blrt)); \ - blrt.storename = FNV1_32_INIT; \ -} - -#define BL_END_RUNTIME() { \ - memset(&blrt, 0, sizeof(blrt)); \ -} - -#ifdef BBSLUA_USAGE -static int bbslua_count; -#endif - -////////////////////////////////////////////////////////////////////////// -// UTILITIES -////////////////////////////////////////////////////////////////////////// - -static void -bl_double2tv(double d, struct timeval *tv) -{ - tv->tv_sec = d; - tv->tv_usec = (d - tv->tv_sec) * BLCONF_U_SECOND; -} - -static double -bl_tv2double(const struct timeval *tv) -{ - double d = tv->tv_sec; - d += tv->tv_usec / (double)BLCONF_U_SECOND; - return d; -} - -static int -bl_peekbreak(float f) -{ - if (input_isfull()) - drop_input(); - if (peek_input(f, BLCONF_BREAK_KEY)) - { - drop_input(); - blrt.abort = 1; - return 1; - } - return 0; -} - -static void -bl_k2s(lua_State* L, int v) -{ - if (v <= 0) - lua_pushnil(L); - else if (v == KEY_TAB) - lua_pushstring(L, "TAB"); - else if (v == '\b' || v == 0x7F) - lua_pushstring(L, "BS"); - else if (v == '\n' || v == '\r' || v == Ctrl('M')) - lua_pushstring(L, "ENTER"); - else if (v < ' ') - lua_pushfstring(L, "^%c", v-1+'A'); - else if (v < 0x100) - lua_pushfstring(L, "%c", v); - else if (v >= KEY_F1 && v <= KEY_F12) - lua_pushfstring(L, "F%d", v - KEY_F1 +1); - else switch(v) - { - case KEY_UP: lua_pushstring(L, "UP"); break; - case KEY_DOWN: lua_pushstring(L, "DOWN"); break; - case KEY_RIGHT: lua_pushstring(L, "RIGHT"); break; - case KEY_LEFT: lua_pushstring(L, "LEFT"); break; - case KEY_HOME: lua_pushstring(L, "HOME"); break; - case KEY_END: lua_pushstring(L, "END"); break; - case KEY_INS: lua_pushstring(L, "INS"); break; - case KEY_DEL: lua_pushstring(L, "DEL"); break; - case KEY_PGUP: lua_pushstring(L, "PGUP"); break; - case KEY_PGDN: lua_pushstring(L, "PGDN"); break; - default: lua_pushnil(L); break; - } -} - -BLAPI_PROTO -bl_newwin(int rows, int cols, const char *title) -{ - // input: (rows, cols, title) - int y = 0, x = 0, n = 0; - int oy = 0, ox = 0; - - if (rows <= 0 || cols <= 0) - return 0; - - getyx(&oy, &ox); - // now, draw the window - newwin(rows, cols, oy, ox); - - if (!title || !*title) - return 0; - - // draw center-ed title - n = strlen_noansi(title); - x = ox + (cols - n)/2; - y = oy + (rows)/2; - move(y, x); - outs(title); - - move(oy, ox); - return 0; -} - -////////////////////////////////////////////////////////////////////////// -// BBSLUA API IMPLEMENTATION -////////////////////////////////////////////////////////////////////////// - -BLAPI_PROTO -bl_getyx(lua_State* L) -{ - int y, x; - getyx(&y, &x); - lua_pushinteger(L, y); - lua_pushinteger(L, x); - return 2; -} - -BLAPI_PROTO -bl_getmaxyx(lua_State* L) -{ - lua_pushinteger(L, t_lines); - lua_pushinteger(L, t_columns); - return 2; -} - -BLAPI_PROTO -bl_move(lua_State* L) -{ - int n = lua_gettop(L); - int y = 0, x = 0; - if (n > 0) - y = lua_tointeger(L, 1); - if (n > 1) - x = lua_tointeger(L, 2); - move_ansi(y, x); - return 0; -} - -BLAPI_PROTO -bl_moverel(lua_State* L) -{ - int n = lua_gettop(L); - int y = 0, x = 0; - getyx(&y, &x); - if (n > 0) - y += lua_tointeger(L, 1); - if (n > 1) - x += lua_tointeger(L, 2); - move(y, x); - getyx(&y, &x); - lua_pushinteger(L, y); - lua_pushinteger(L, x); - return 2; -} - -BLAPI_PROTO -bl_clear(lua_State* L) -{ - (void)L; /* to avoid warnings */ - clear(); - return 0; -} - -BLAPI_PROTO -bl_clrtoeol(lua_State* L) -{ - (void)L; /* to avoid warnings */ - clrtoeol(); - return 0; -} - -BLAPI_PROTO -bl_clrtobot(lua_State* L) -{ - (void)L; /* to avoid warnings */ - clrtobot(); - return 0; -} - -BLAPI_PROTO -bl_refresh(lua_State* L) -{ - (void)L; /* to avoid warnings */ - // refresh(); - // Seems like that most people don't understand the relationship - // between refresh() and input queue, so let's force update here. - doupdate(); - return 0; -} - -BLAPI_PROTO -bl_addstr(lua_State* L) -{ - int n = lua_gettop(L); - int i = 1; - for (i = 1; i <= n; i++) - { - const char *s = lua_tostring(L, i); - if(s) - outs(s); - } - return 0; -} - -BLAPI_PROTO -bl_rect(lua_State *L) -{ - // input: (rows, cols, title) - int rows = 1, cols = 1; - int n = lua_gettop(L); - const char *title = NULL; - - if (n > 0) - rows = lua_tointeger(L, 1); - if (n > 1) - cols = lua_tointeger(L, 2); - if (n > 2) - title = lua_tostring(L, 3); - if (rows <= 0 || cols <= 0) - return 0; - - // now, draw the rectangle - bl_newwin(rows, cols, title); - return 0; -} - -BLAPI_PROTO -bl_print(lua_State* L) -{ - bl_addstr(L); - outc('\n'); - return 0; -} - -BLAPI_PROTO -bl_getch(lua_State* L) -{ - int c = igetch(); - if (c == BLCONF_BREAK_KEY) - { - drop_input(); - blrt.abort = 1; - return lua_yield(L, 0); - } - bl_k2s(L, c); - return 1; -} - - -BLAPI_PROTO -bl_getstr(lua_State* L) -{ - int y, x; - // TODO not using fixed length here? - char buf[PATHLEN] = ""; - int len = 2, echo = 1; - int n = lua_gettop(L); - const char *pmsg = NULL; - - if (n > 0) - len = lua_tointeger(L, 1); - if (n > 1) - echo = lua_tointeger(L, 2); - if (n > 2) - pmsg = lua_tostring(L, 3); - - if (len < 2) - len = 2; - if (len >= sizeof(buf)) - len = sizeof(buf)-1; - /* - * this part now done in getdata_str - if (pmsg && *pmsg) - { - strlcpy(buf, pmsg, sizeof(buf)); - } - */ - - // TODO process Ctrl-C here - getyx(&y, &x); - if (!pmsg) pmsg = ""; - len = getdata_str(y, x, NULL, buf, len, echo, pmsg); - if (len <= 0) - { - len = 0; - // check if we got Ctrl-C? (workaround in getdata) - // TODO someday write 'ungetch()' in io.c to prevent - // such workaround. - if (buf[1] == Ctrl('C')) - { - drop_input(); - blrt.abort = 1; - return lua_yield(L, 0); - } - lua_pushstring(L, ""); - } - else - { - lua_pushstring(L, buf); - } - // return len ? 1 : 0; - return 1; -} - -BLAPI_PROTO -bl_kbhit(lua_State *L) -{ - int n = lua_gettop(L); - double f = 0.1f; - - if (n > 0) - f = (double)lua_tonumber(L, 1); - - if (f < BLCONF_KBHIT_TMIN) f = BLCONF_KBHIT_TMIN; - if (f > BLCONF_KBHIT_TMAX) f = BLCONF_KBHIT_TMAX; - - refresh(); - if (num_in_buf() || wait_input(f, 0)) - lua_pushboolean(L, 1); - else - lua_pushboolean(L, 0); - return 1; -} - -BLAPI_PROTO -bl_kbreset(lua_State *L) -{ - // peek input queue first! - if (bl_peekbreak(BLCONF_PEEK_TIME)) - return lua_yield(L, 0); - - drop_input(); - return 0; -} - -BLAPI_PROTO -bl_sleep(lua_State *L) -{ - int n = lua_gettop(L); - double us = 0, nus = 0; - - // update screen first. - bl_refresh(L); - - if (n > 0) - us = lua_tonumber(L, 1); - if (us < BLCONF_SLEEP_TMIN) us = BLCONF_SLEEP_TMIN; - if (us > BLCONF_SLEEP_TMAX) us = BLCONF_SLEEP_TMAX; - nus = us; - -#ifdef _WIN32 - - Sleep(us * 1000); - -#else // !_WIN32 - { - struct timeval tp, tdest; - - gettimeofday(&tp, NULL); - - // nus is the destination time - nus = bl_tv2double(&tp) + us; - bl_double2tv(nus, &tdest); - - while ( (tp.tv_sec < tdest.tv_sec) || - ((tp.tv_sec == tdest.tv_sec) && (tp.tv_usec < tdest.tv_usec))) - { - // calculate new peek time - us = nus - bl_tv2double(&tp); - - // check if input key is system break key. - if (bl_peekbreak(us)) - return lua_yield(L, 0); - - // check time - gettimeofday(&tp, NULL); - } - } -#endif // !_WIN32 - - return 0; -} - -BLAPI_PROTO -bl_kball(lua_State *L) -{ - // first, sleep by given seconds - int r = 0, oldr = 0, i = 0; - - r = bl_sleep(L); - if (blrt.abort) - return r; - - // pop all arguments - lua_pop(L, lua_gettop(L)); - - -#ifdef _WIN32 - while (peekch(0)) - { - bl_k2s(L, igetch()); - i++; - } -#else - // next, collect all input and return. - if (num_in_buf() < 1) - return 0; - - oldr = num_in_buf() +1; - i = 0; - - while ( i < LUA_MINSTACK && - (r = num_in_buf()) > 0 && oldr > r) - { - oldr = r; - bl_k2s(L, igetch()); - i++; - } -#endif - - return i; -} - - -BLAPI_PROTO -bl_pause(lua_State* L) -{ - int n = lua_gettop(L); - const char *s = NULL; - if (n > 0) - s = lua_tostring(L, 1); - - n = vmsg(s); - if (n == BLCONF_BREAK_KEY) - { - drop_input(); - blrt.abort = 1; - return lua_yield(L, 0); - } - bl_k2s(L, n); - return 1; -} - -BLAPI_PROTO -bl_title(lua_State* L) -{ - int n = lua_gettop(L); - const char *s = NULL; - if (n > 0) - s = lua_tostring(L, 1); - if (s == NULL) - return 0; - - stand_title(s); - return 0; -} - -BLAPI_PROTO -bl_ansi_color(lua_State *L) -{ - char buf[PATHLEN] = ESC_STR "["; - char *p = buf + strlen(buf); - int i = 1; - int n = lua_gettop(L); - if (n >= 10) n = 10; - for (i = 1; i <= n; i++) - { - if (i > 1) *p++ = ';'; - sprintf(p, "%d", (int)lua_tointeger(L, i)); - p += strlen(p); - } - *p++ = 'm'; - *p = 0; - lua_pushstring(L, buf); - return 1; -} - -BLAPI_PROTO -bl_strip_ansi(lua_State *L) -{ - int n = lua_gettop(L); - const char *s = NULL; - char *s2 = NULL; - size_t os2 = 0; - - if (n < 1 || (s = lua_tostring(L, 1)) == NULL || - *s == 0) - { - lua_pushstring(L, ""); - return 1; - } - - os2 = strlen(s)+1; - s2 = (char*) lua_newuserdata(L, os2); - strip_ansi(s2, s, STRIP_ALL); - lua_pushstring(L, s2); - lua_remove(L, -2); - return 1; -} - -BLAPI_PROTO -bl_attrset(lua_State *L) -{ - char buf[PATHLEN] = ESC_STR "["; - char *p = buf + strlen(buf); - int i = 1; - int n = lua_gettop(L); - if (n == 0) - outs(ANSI_RESET); - for (i = 1; i <= n; i++) - { - sprintf(p, "%dm",(int)lua_tointeger(L, i)); - outs(buf); - } - return 0; -} - -BLAPI_PROTO -bl_time(lua_State *L) -{ - syncnow(); - lua_pushinteger(L, now); - return 1; -} - -BLAPI_PROTO -bl_ctime(lua_State *L) -{ - syncnow(); - lua_pushstring(L, ctime4(&now)); - return 1; -} - -BLAPI_PROTO -bl_clock(lua_State *L) -{ - double d = 0; - -#ifdef _WIN32 - - // XXX this is a fast hack because we don't want to do 64bit calculation. - SYSTEMTIME st; - GetSystemTime(&st); - syncnow(); - // XXX the may be some latency between our GetSystemTime and syncnow. - // So build again the "second" part. - d = (int)((now / 60) * 60); - d += st.wSecond; - d += (st.wMilliseconds / 1000.0f); - -#else // !_WIN32 - - struct timeval tp; - gettimeofday(&tp, NULL); - d = bl_tv2double(&tp); - -#endif // !_WIN32 - - lua_pushnumber(L, d); - return 1; -} - -////////////////////////////////////////////////////////////////////////// -// BBS-Lua Storage System -////////////////////////////////////////////////////////////////////////// -static int -bls_getcat(const char *s) -{ - if (!s || !*s) - return BLS_INVALID; - if (strcmp(s, BLSCONF_GLOBAL_VAL) == 0) - return BLS_GLOBAL; - else if (strcmp(s, BLSCONF_USER_VAL) == 0) - return BLS_USER; - return BLS_INVALID; -} - -static int -bls_getlimit(const char *p) -{ - switch(bls_getcat(p)) - { - case BLS_GLOBAL: - return BLSCONF_GMAXSIZE; - case BLS_USER: - return BLSCONF_UMAXSIZE; - } - return 0; -} - -static int -bls_setfn(char *fn, size_t sz, const char *p) -{ - *fn = 0; - switch(bls_getcat(p)) - { - case BLS_GLOBAL: - snprintf(fn, sz, "%s/" BLSCONF_PREFIX "U%08x", - BLSCONF_GPATH, blrt.storename); - return 1; - - case BLS_USER: - setuserfile(fn, BLSCONF_UPATH); - mkdir(fn, 0755); - assert(strlen(fn) +8 <= sz); - snprintf(fn + strlen(fn), - sz - strlen(fn), - "/" BLSCONF_PREFIX "G%08x", blrt.storename); - return 1; - } - return 0; -} - -BLAPI_PROTO -bls_iolimit(lua_State *L) -{ - lua_pushinteger(L, BLSCONF_MAXIO); - return 1; -} - -BLAPI_PROTO -bls_limit(lua_State *L) -{ - int n = lua_gettop(L); - const char *s = NULL; - if (n > 0) - s = lua_tostring(L, 1); - lua_pushinteger(L, bls_getlimit(s)); - return 1; -} - -BLAPI_PROTO -bls_load(lua_State *L) -{ - int n = lua_gettop(L); - const char *cat = NULL; - char fn[PATHLEN]; - - if (blrt.iocounter >= BLSCONF_MAXIO) - { - lua_pushnil(L); - return 1; - } - - if (n != 1) - { - lua_pushnil(L); - return 1; - } - cat = lua_tostring(L, 1); // category - if (!cat) - { - lua_pushnil(L); - return 1; - } - - blrt.iocounter++; - // read file! - if (bls_setfn(fn, sizeof(fn), cat)) - { - int fd = open(fn, O_RDONLY); - if (fd >= 0) - { - char buf[2048]; - luaL_Buffer b; - - luaL_buffinit(L, &b); - while ((n = read(fd, buf, sizeof(buf))) > 0) - luaL_addlstring(&b, buf, n); - close(fd); - luaL_pushresult(&b); - } else { - lua_pushnil(L); - } - } else { - lua_pushnil(L); - } - return 1; -} - -BLAPI_PROTO -bls_save(lua_State *L) -{ - int n = lua_gettop(L), fd = -1; - int limit = 0, slen = 0; - const char *s = NULL, *cat = NULL; - char fn[PATHLEN] = "", ret = 0; - - if (blrt.iocounter >= BLSCONF_MAXIO) - { - lua_pushboolean(L, 0); - return 1; - } - - if (n != 2) { lua_pushboolean(L, 0); return 1; } - - cat = lua_tostring(L, 1); // category - s = lua_tostring(L, 2); // data - limit = bls_getlimit(cat); - - if (!cat || !s || limit < 1) - { - lua_pushboolean(L, 0); - return 1; - } - - slen = lua_objlen(L, 2); - if (slen >= limit) slen = limit; - - blrt.iocounter++; - // write file! - if (bls_setfn(fn, sizeof(fn), cat)) - { - fd = open(fn, O_WRONLY|O_CREAT, 0644); - if (fd >= 0) - { - write(fd, s, slen); - close(fd); - ret = 1; - } - } - - lua_pushboolean(L, ret); - return 1; -} - -////////////////////////////////////////////////////////////////////////// -// BBSLUA LIBRARY -////////////////////////////////////////////////////////////////////////// - -static const struct luaL_reg lib_bbslua [] = { - /* curses output */ - { "getyx", bl_getyx }, - { "getmaxyx", bl_getmaxyx }, - { "move", bl_move }, - { "moverel", bl_moverel }, - { "clear", bl_clear }, - { "clrtoeol", bl_clrtoeol }, - { "clrtobot", bl_clrtobot }, - { "refresh", bl_refresh }, - { "addstr", bl_addstr }, - { "outs", bl_addstr }, - { "print", bl_print }, - /* input */ - { "getch", bl_getch }, - { "getdata", bl_getstr }, - { "getstr", bl_getstr }, - { "kbhit", bl_kbhit }, - { "kbreset", bl_kbreset }, - { "kball", bl_kball }, - /* advanced output */ - { "rect", bl_rect }, - /* BBS utilities */ - { "pause", bl_pause }, - { "title", bl_title }, - /* time */ - { "time", bl_time }, - { "now", bl_time }, - { "clock", bl_clock }, - { "ctime", bl_ctime }, - { "sleep", bl_sleep }, - /* ANSI helpers */ - { "ANSI_COLOR", bl_ansi_color }, - { "color", bl_attrset }, - { "attrset", bl_attrset }, - { "strip_ansi", bl_strip_ansi }, - { NULL, NULL}, -}; - -static const struct luaL_reg lib_store [] = { - { "load", bls_load }, - { "save", bls_save }, - { "limit", bls_limit }, - { "iolimit", bls_iolimit }, - { NULL, NULL}, -}; - -// non-standard modules in bbsluaext.c -LUALIB_API int luaopen_bit (lua_State *L); - -static const luaL_Reg bbslualibs[] = { - // standard modules - {"", luaopen_base}, - - // {LUA_LOADLIBNAME, luaopen_package}, - {LUA_TABLIBNAME, luaopen_table}, - // {LUA_IOLIBNAME, luaopen_io}, - // {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - // {LUA_DBLIBNAME, luaopen_debug}, - - // bbslua-ext modules - {"bit", luaopen_bit}, - - {NULL, NULL} -}; - - -LUALIB_API void bbsluaL_openlibs (lua_State *L) { - const luaL_Reg *lib = bbslualibs; - for (; lib->func; lib++) { - lua_pushcfunction(L, lib->func); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); - } -} - - -// Constant registration - -typedef struct bbsluaL_RegStr { - const char *name; - const char *val; -} bbsluaL_RegStr; - -typedef struct bbsluaL_RegNum { - const char *name; - lua_Number val; -} bbsluaL_RegNum; - -static const bbsluaL_RegStr bbsluaStrs[] = { - {"ESC", ESC_STR}, - {"ANSI_RESET", ANSI_RESET}, - {"sitename", BBSNAME}, - {NULL, NULL}, -}; - -static const bbsluaL_RegNum bbsluaNums[] = { - {"interface", BBSLUA_INTERFACE_VER}, - {NULL, 0}, -}; - -static void -bbsluaRegConst(lua_State *L) -{ - int i = 0; - - // unbind unsafe API - lua_pushnil(L); lua_setglobal(L, "dofile"); - lua_pushnil(L); lua_setglobal(L, "loadfile"); - - // global - lua_pushcfunction(L, bl_print); - lua_setglobal(L, "print"); - - // bbs.* - lua_getglobal(L, "bbs"); - for (i = 0; bbsluaStrs[i].name; i++) - { - lua_pushstring(L, bbsluaStrs[i].val); - lua_setfield(L, -2, bbsluaStrs[i].name); - } - - for (i = 0; bbsluaNums[i].name; i++) - { - lua_pushnumber(L, bbsluaNums[i].val); - lua_setfield(L, -2, bbsluaNums[i].name); - } - // dynamic info - lua_pushstring(L, BLCONF_CURRENT_USERID); - lua_setfield(L, -2, "userid"); - lua_pushstring(L, BLCONF_CURRENT_USERNICK); - lua_setfield(L, -2, "usernick"); - - lua_pop(L, 1); - -#ifdef BLSCONF_ENABLED - // store.* - lua_getglobal(L, "store"); - lua_pushstring(L, BLSCONF_USER_VAL); - lua_setfield(L, -2, "USER"); - lua_pushstring(L, BLSCONF_GLOBAL_VAL); - lua_setfield(L, -2, "GLOBAL"); - lua_pop(L, 1); -#endif // BLSCONF_ENABLED -} - -////////////////////////////////////////////////////////////////////////// -// BBSLUA ENGINE UTILITIES -////////////////////////////////////////////////////////////////////////// - -static void -bbsluaHook(lua_State *L, lua_Debug* ar) -{ - // vmsg("bbslua HOOK!"); - if (blrt.abort) - { - drop_input(); - lua_yield(L, 0); - return; - } - - if (ar->event != LUA_HOOKCOUNT) - return; -#ifdef BBSLUA_USAGE - bbslua_count += BLCONF_EXEC_COUNT; -#endif - - // now, peek and check - if (input_isfull()) - drop_input(); - - // refresh(); - - // check if input key is system break key. - if (bl_peekbreak(BLCONF_PEEK_TIME)) - { - lua_yield(L, 0); - return; - } -} - -static char * -bbslua_attach(const char *fpath, size_t *plen) -{ - char *buf = NULL; - -#ifdef BLCONF_MMAP_ATTACH - struct stat st; - int fd = open(fpath, O_RDONLY); - - *plen = 0; - - if (fd < 0) return buf; - if (fstat(fd, &st) || ((*plen = st.st_size) < 1) || S_ISDIR(st.st_mode)) - { - close(fd); - return buf; - } - *plen = *plen +1; - - buf = mmap(NULL, *plen, PROT_READ, MAP_SHARED, fd, 0); - close(fd); - - if (buf == NULL || buf == MAP_FAILED) - { - *plen = 0; - return NULL; - } - madvise(buf, *plen, MADV_SEQUENTIAL); - -#else // !BLCONF_MMAP_ATTACH - - FILE *fp = fopen(fpath, "rt"); - *plen = 0; - if (!fp) - return NULL; - fseek(fp, 0, SEEK_END); - *plen = ftell(fp); - buf = (char*) malloc (*plen); - rewind(fp); - fread(buf, *plen, 1, fp); - -#endif // !BLCONF_MMAP_ATTACH - - return buf; -} - -static void -bbslua_detach(char *p, int len) -{ -#ifdef BLCONF_MMAP_ATTACH - munmap(p, len); -#else // !BLCONF_MMAP_ATTACH - free(p); -#endif // !BLCONF_MMAP_ATTACH -} - -int -bbslua_isHeader(const char *ps, const char *pe) -{ - int szsig = strlen(BBSLUA_SIGNATURE); - if (ps + szsig > pe) - return 0; - if (strncmp(ps, BBSLUA_SIGNATURE, szsig) == 0) - return 1; - return 0; -} - -static int -bbslua_detect_range(char **pbs, char **pbe, int *lineshift) -{ - int szsig = strlen(BBSLUA_SIGNATURE); - char *bs, *be, *ps, *pe; - int line = 0; - - bs = ps = *pbs; - be = pe = *pbe; - - // find start - while (ps + szsig < pe) - { - if (strncmp(ps, BBSLUA_SIGNATURE, szsig) == 0) - break; - // else, skip to next line - while (ps + szsig < pe && *ps++ != '\n'); - line++; - } - *lineshift = line; - - if (!(ps + szsig < pe)) - return 0; - - *pbs = ps; - *pbe = be; - - // find tail by SIGNATURE - pe = ps + 1; - while (pe + szsig < be) - { - if (strncmp(pe, BBSLUA_SIGNATURE, szsig) == 0) - break; - // else, skip to next line - while (pe + szsig < be && *pe++ != '\n'); - } - - if (pe + szsig < be) - { - // found sig, end at such line. - pe--; - *pbe = pe; - } else { - // abort. - *pbe = NULL; - *pbs = NULL; - return 0; - } - - // prevent trailing zeros - pe = *pbe; - while (pe > ps && !*pe) - pe--; - *pbe = pe; - - return 1; -} - -////////////////////////////////////////////////////////////////////////// -// BBSLUA TOC Processing -////////////////////////////////////////////////////////////////////////// - -static const char *bbsluaTocTags[] = -{ - "interface", - "latestref", - - // BLCONF_PRINT_TOC_INDEX - "title", - "notes", - "author", - "version", - "date", - NULL -}; - -static const char *bbsluaTocPrompts[] = -{ - "¬É±ª©¥»", - "³Ì·sª©¥»", - - // BLCONF_PRINT_TOC_INDEX - "¦WºÙ", - "»¡©ú", - "§@ªÌ", - "ª©¥»", - "¤é´Á", - NULL -}; - -int -bbslua_load_TOC(lua_State *L, const char *bs, const char *be, char **ppc) -{ - unsigned char *ps = NULL, *pe = NULL; - int i = 0; - - lua_newtable(L); - *ppc = NULL; - - while (bs < be) - { - // find stripped line start, end - ps = pe = (unsigned char *) bs; - while (pe < (unsigned char*)be && *pe != '\n' && *pe != '\r') - pe ++; - bs = (char*)pe+1; - while (ps < pe && *ps <= ' ') ps++; - while (pe > ps && *(pe-1) <= ' ') pe--; - // at least "--" - if (pe < ps+2) - break; - if (*ps++ != '-' || *ps++ != '-') - break; - while (ps < pe && *ps <= ' ') ps++; - // empty entry? - if (ps >= pe) - continue; - // find pattern - for (i = 0; bbsluaTocTags[i]; i++) - { - int l = strlen(bbsluaTocTags[i]); - if (ps + l > pe) - continue; - if (strncasecmp((char*)ps, bbsluaTocTags[i], l) != 0) - continue; - ps += l; - // found matching pattern, now find value - while (ps < pe && *ps <= ' ') ps++; - if (ps >= pe || *ps++ != ':') - break; - while (ps < pe && *ps <= ' ') ps++; - // finally, (ps, pe) is the value! - if (ps >= pe) - break; - - lua_pushlstring(L, (char*)ps, pe-ps); - - // accept only real floats for interface ([0]) - if (i == 0 && lua_tonumber(L, -1) <= 0) - { - lua_pop(L, 1); - } - else - { - lua_setfield(L, -2, bbsluaTocTags[i]); - } - break; - } - } - - if (ps >= (unsigned char*)bs && ps < (unsigned char*)be) - *ppc = (char*)ps; - lua_setglobal(L, "toc"); - return 0; -} - -static void -fullmsg(const char *s) -{ - clrtoeol(); - prints("%-*.*s\n", t_columns-1, t_columns-1, s); -} - -void -bbslua_logo(lua_State *L) -{ - int y, by = b_lines -1; // print - back from bottom - int i = 0; - double tocinterface = 0; - int tocs = 0; - char msg[STRLEN]; - - // get toc information - lua_getglobal(L, "toc"); - lua_getfield(L, -1, bbsluaTocTags[0]); - tocinterface = lua_tonumber(L, -1); lua_pop(L, 1); - - // query print-able toc tags - for (i = BLCONF_PRINT_TOC_INDEX; bbsluaTocTags[i]; i++) - { - lua_getfield(L, -1, bbsluaTocTags[i]); - if (lua_tostring(L, -1)) - tocs++; - lua_pop(L, 1); - } - - // prepare logo window - grayout(0, b_lines, GRAYOUT_DARK); - - // print compatibility test - // now (by) is the base of new information - if (tocinterface == 0) - { - by -= 4; y = by+2; - move(y-1, 0); - outs(ANSI_COLOR(0;31;47)); - fullmsg(""); - fullmsg(" ¡¶ ¦¹µ{¦¡¯Ê¤Ö¬Û®e©Ê¸ê°T¡A±z¥i¯àµLªk¥¿±`°õ¦æ"); - fullmsg(" Y°õ¦æ¥X²{¿ù»~¡A½Ð¦Vì§@ªÌ¨ú±o·sª©"); - fullmsg(""); - } - else if (tocinterface > BBSLUA_INTERFACE_VER) - { - by -= 4; y = by+2; - move(y-1, 0); - outs(ANSI_COLOR(0;1;37;41)); - fullmsg(""); - snprintf(msg, sizeof(msg), - " ¡¶ ¦¹µ{¦¡¨Ï¥Î·sª©ªº BBS-Lua ³W®æ (%0.3f)¡A±z¥i¯àµLªk¥¿±`°õ¦æ", - tocinterface); - fullmsg(msg); - fullmsg(" Y°õ¦æ¥X²{¿ù»~¡A«Øij±z«·sµn¤J BBS «á¦A«¸Õ"); - fullmsg(""); - } - else if (tocinterface == BBSLUA_INTERFACE_VER) - { - // do nothing! - } - else - { - // should be comtaible - // prints("¬Û®e (%.03f)", tocinterface); - } - - // print toc, if any. - if (tocs) - { - y = by - 1 - tocs; - by = y-1; - - move(y, 0); outs(ANSI_COLOR(0;1;30;47)); - fullmsg(""); - - // now try to print all TOC infos - for (i = BLCONF_PRINT_TOC_INDEX; bbsluaTocTags[i]; i++) - { - lua_getfield(L, -1, bbsluaTocTags[i]); - if (!lua_isstring(L, -1)) - { - lua_pop(L, 1); - continue; - } - move(++y, 0); - snprintf(msg, sizeof(msg), " %s: %-.*s", - bbsluaTocPrompts[i], STRLEN-12, lua_tostring(L, -1)); - msg[sizeof(msg)-1] = 0; - fullmsg(msg); - lua_pop(L, 1); - } - fullmsg(""); - } - - // print caption - move(by-2, 0); outc('\n'); - outs(ANSI_COLOR(0;1;37;44)); - snprintf(msg, sizeof(msg), - " ¡½ BBS-Lua %.03f (Build " __DATE__ " " __TIME__") ", - (double)BBSLUA_INTERFACE_VER); - fullmsg(msg); - - // system break key prompt - { - int sz = t_columns -1; - const char - *prompt1 = " ´£¿ô±z°õ¦æ¤¤ÀH®É¥i«ö ", - *prompt2 = "[Ctrl-C]", - *prompt3 = " ±j¨î¤¤Â_ BBS-Lua µ{¦¡"; - sz -= strlen(prompt1); - sz -= strlen(prompt2); - sz -= strlen(prompt3); - outs(ANSI_COLOR(22;37)); outs(prompt1); - outs(ANSI_COLOR(1;31)); outs(prompt2); - outs(ANSI_COLOR(0;37;44));outs(prompt3); - prints("%*s", sz, ""); - outs(ANSI_RESET); - } - lua_pop(L, 1); -} - -////////////////////////////////////////////////////////////////////////// -// BBSLUA Script Loader -////////////////////////////////////////////////////////////////////////// - -typedef struct LoadS { - const char *s; - size_t size; - int lineshift; -} LoadS; - -static const char* bbslua_reader(lua_State *L, void *ud, size_t *size) -{ - LoadS *ls = (LoadS *)ud; - (void)L; - if (ls->size == 0) return NULL; - if (ls->lineshift > 0) { - const char *linefeed = "\n"; - *size = 1; - ls->lineshift--; - return linefeed; - } - *size = ls->size; - ls->size = 0; - return ls->s; -} - -static int bbslua_loadbuffer (lua_State *L, const char *buff, size_t size, - const char *name, int lineshift) { - LoadS ls; - ls.s = buff; - ls.size = size; - ls.lineshift = lineshift; - return lua_load(L, bbslua_reader, &ls, name); -} - -typedef struct AllocData { - size_t alloc_size; - size_t max_alloc_size; - size_t alloc_limit; -} AllocData; - -static void alloc_init(AllocData *ad) -{ - memset(ad, 0, sizeof(*ad)); - // real limit is not determined yet, just assign a big value - ad->alloc_limit = 20*1048576; -} - -static void *allocf (void *ud, void *ptr, size_t osize, size_t nsize) { - /* TODO use our own allocator, for better memory control, avoid fragment and leak */ - AllocData *ad = (AllocData*)ud; - - if (ad->alloc_size + nsize - osize > ad->alloc_limit) { - return NULL; - } - ad->alloc_size += nsize - osize; - if (ad->alloc_size > ad->max_alloc_size) { - ad->max_alloc_size = ad->alloc_size; - } - if (nsize == 0) { - free(ptr); - return NULL; - } - else - return realloc(ptr, nsize); -} -static int panic (lua_State *L) { - (void)L; /* to avoid warnings */ - fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", - lua_tostring(L, -1)); - return 0; -} - -void bbslua_loadLatest(lua_State *L, - char **pbs, char **pps, char **ppe, char **ppc, int *psz, - int *plineshift, char *bfpath, const char **pfpath) -{ - int r = 1; // max redirect for one article only. - - do { - char *xbs = NULL, *xps = NULL, *xpe = NULL, *xpc = NULL; - int xlineshift = 0; - size_t xsz; - const char *lastref = NULL; - char loadnext = 0, isnewver = 0; - - // detect file - xbs = bbslua_attach(bfpath, &xsz); - if (!xbs) - break; - - xps = xbs; - xpe = xps + xsz; - - if(!bbslua_detect_range(&xps, &xpe, &xlineshift)) - { - // not detected - bbslua_detach(xbs, xsz); - break; - } - - // detect and verify TOC meta data - lua_getglobal(L, "toc"); // stack 1 - if (lua_istable(L, -1)) - { - const char *oref, *otitle, *nref, *ntitle; - // load and verify tocinfo - lua_getfield(L, -1, "latestref"); // stack 2 - oref = lua_tostring(L, -1); - lua_getfield(L, -2, "title"); // stack 3 - otitle = lua_tostring(L, -1); - bbslua_load_TOC(L, xps, xpe, &xpc); - lua_getglobal(L, "toc"); // stack 4 - lua_getfield(L, -1, "latestref"); // stack 5 - nref = lua_tostring(L, -1); - lua_getfield(L, -2, "title"); // stack 6 - ntitle = lua_tostring(L, -1); - - if (oref && nref && otitle && ntitle && - strcmp(oref, nref) == 0 && - strcmp(otitle, ntitle) == 0) - isnewver = 1; - - // pop all - lua_pop(L, 5); // stack = 1 (old toc) - if (!isnewver) - lua_setglobal(L, "toc"); - else - lua_pop(L, 1); - } else { - lua_pop(L, 1); - bbslua_load_TOC(L, xps, xpe, &xpc); - } - - if (*pbs && !isnewver) - { - // different. - bbslua_detach(xbs, xsz); - break; - } - - // now, apply current buffer - if (*pbs) - { - bbslua_detach(*pbs, *psz); - // XXX fpath=bfpath, supporting only one level redirection now. - *pfpath = bfpath; - } - *pbs = xbs; *pps = xps; *ppe = xpe; *psz = xsz; - *ppc = xpc; - *plineshift = xlineshift; - -#ifdef AID_DISPLAYNAME - // quick exit - if (r <= 0) - break; - - // LatestRef only works if system supports AID. - // try to load next reference. - lua_getglobal(L, "toc"); // stack 1 - lua_getfield(L, -1, "latestref"); // stack 2 - lastref = lua_tostring(L, -1); - - while (lastref && *lastref) - { - // try to load by AID - char bn[IDLEN+1] = ""; - aidu_t aidu = 0; - unsigned char *p = (unsigned char*)bn; - - if (*lastref == '#') lastref++; - aidu = aidc2aidu((char*)lastref); - if (aidu <= 0) break; - - while (*lastref > ' ') lastref ++; // lastref points to zero of space - while (*lastref && *lastref <= ' ') lastref++; // lastref points to zero or board name - if (*lastref == '(') lastref ++; - - if (!*lastref) break; - strlcpy(bn, lastref, sizeof(bn)); - // truncate board name - // (not_alnum(ch) && ch != '_' && ch != '-' && ch != '.') - while (*p && - (isalnum(*p) || *p == '_' || *p == '-' || *p == '.')) p++; - *p = 0; - if (bn[0]) - { - bfpath[0] = 0; - setaidfile(bfpath, bn, aidu); - } - - if (bfpath[0]) - loadnext = 1; - break; - } - lua_pop(L, 2); - - if (loadnext) continue; -#endif // AID_DISPLAYNAME - break; - - } while (r-- > 0); -} - -////////////////////////////////////////////////////////////////////////// -// BBSLUA Hash -////////////////////////////////////////////////////////////////////////// - -#if 0 -static int -bbslua_hashWriter(lua_State *L, const void *p, size_t sz, void *ud) -{ - Fnv32_t *phash = (Fnv32_t*) ud; - *phash = fnv_32_buf(p, sz, *phash); - return 0; -} - -static Fnv32_t -bbslua_f2hash(lua_State *L) -{ - Fnv32_t fnvseed = FNV1_32_INIT; - lua_dump(L, bbslua_hashWriter, &fnvseed); - return fnvseed; -} - -static Fnv32_t -bbslua_str2hash(const char *str) -{ - if (!str) - return 0; - return fnv_32_str(str, FNV1_32_INIT); -} -#endif - -static Fnv32_t -bbslua_path2hash(const char *path) -{ - Fnv32_t seed = FNV1_32_INIT; - if (!path) - return 0; - if (path[0] != '/') // relative, append BBSHOME - seed = fnv_32_str(BBSHOME "/", seed); - return fnv_32_str(path, seed); -} - -////////////////////////////////////////////////////////////////////////// -// BBSLUA Main -////////////////////////////////////////////////////////////////////////// - -int -bbslua(const char *fpath) -{ - int r = 0; - lua_State *L; - char *bs = NULL, *ps = NULL, *pe = NULL, *pc = NULL; - char bfpath[PATHLEN] = ""; - int sz = 0; - int lineshift = 0; - AllocData ad; -#ifdef BBSLUA_USAGE - struct rusage rusage_begin, rusage_end; - struct timeval lua_begintime, lua_endtime; - gettimeofday(&lua_begintime, NULL); - getrusage(0, &rusage_begin); -#endif - -#ifdef UMODE_BBSLUA - unsigned int prevmode = getutmpmode(); -#endif - - // re-entrant not supported! - if (blrt.running) - return 0; - - // initialize runtime - BL_INIT_RUNTIME(); - -#ifdef BBSLUA_USAGE - bbslua_count = 0; -#endif - - // init lua - alloc_init(&ad); - L = lua_newstate(allocf, &ad); - if (!L) - return 0; - lua_atpanic(L, &panic); - - strlcpy(bfpath, fpath, sizeof(bfpath)); - - // load file - bbslua_loadLatest(L, &ps, &ps, &pe, &pc, &sz, &lineshift, bfpath, &fpath); - - if (!ps || !pe || ps >= pe) - { - if (bs) - bbslua_detach(bs, sz); - lua_close(L); - vmsg("BBS-Lua ¸ü¤J¿ù»~: ¥¼§t BBS-Lua µ{¦¡"); - return 0; - } - - // init library - bbsluaL_openlibs(L); - luaL_openlib(L, "bbs", lib_bbslua, 0); - -#ifdef BLSCONF_ENABLED - luaL_openlib(L, "store", lib_store, 0); -#endif // BLSCONF_ENABLED - - bbsluaRegConst(L); - - // load script - r = bbslua_loadbuffer(L, ps, pe-ps, "BBS-Lua", lineshift); - - // build hash or store name - blrt.storename = bbslua_path2hash(fpath); - // vmsgf("BBS-Lua Hash: %08X", blrt.storename); - - // unmap - bbslua_detach(bs, sz); - - if (r != 0) - { - const char *errmsg = lua_tostring(L, -1); - lua_close(L); - outs(ANSI_RESET); - move(b_lines-3, 0); clrtobot(); - outs("\n"); - outs(errmsg); - vmsg("BBS-Lua ¸ü¤J¿ù»~: ½Ð³qª¾§@ªÌ×¥¿µ{¦¡½X¡C"); - return 0; - } - -#ifdef UMODE_BBSLUA - setutmpmode(UMODE_BBSLUA); -#endif - - bbslua_logo(L); - vmsgf("´£¿ô±z°õ¦æ¤¤ÀH®É¥i«ö [Ctrl-C] ±j¨î¤¤Â_ BBS-Lua µ{¦¡"); - - // ready for running - clear(); - blrt.running =1; - lua_sethook(L, bbsluaHook, LUA_MASKCOUNT, BLCONF_EXEC_COUNT ); - - refresh(); - // check is now done inside hook - r = lua_resume(L, 0); - - // even if r == yield, let's abort - you cannot yield main thread. - - if (r != 0) - { - const char *errmsg = lua_tostring(L, -1); - move(b_lines-3, 0); clrtobot(); - outs("\n"); - if (errmsg) outs(errmsg); - } - - lua_close(L); - blrt.running =0; - drop_input(); -#ifdef BBSLUA_USAGE - { - double cputime; - double load; - double walltime; - getrusage(0, &rusage_end); - gettimeofday(&lua_endtime, NULL); - cputime = bl_tv2double(&rusage_end.ru_utime) - bl_tv2double(&rusage_begin.ru_utime); - walltime = bl_tv2double(&lua_endtime) - bl_tv2double(&lua_begintime); - load = cputime / walltime; - log_filef("log/bbslua.log", LOG_CREAT, - "maxalloc=%d leak=%d op=%d cpu=%.3f Mop/s=%.1f load=%f file=%s\n", - (int)ad.max_alloc_size, (int)ad.alloc_size, - bbslua_count, cputime, bbslua_count / cputime / 1000000.0, load * 100, - fpath); - } -#endif - - // grayout(0, b_lines, GRAYOUT_DARK); - move(b_lines, 0); clrtoeol(); - vmsgf("BBS-Lua °õ¦æµ²§ô%s¡C", - blrt.abort ? " (¨Ï¥ÎªÌ¤¤Â_)" : r ? " (µ{¦¡¿ù»~)" : ""); - BL_END_RUNTIME(); - clear(); - -#ifdef UMODE_BBSLUA - setutmpmode(prevmode); -#endif - - return 0; -} - -// vim:ts=4:sw=4:expandtab diff --git a/mbbsd/bbsluaext.c b/mbbsd/bbsluaext.c deleted file mode 100644 index ee3521ea..00000000 --- a/mbbsd/bbsluaext.c +++ /dev/null @@ -1,83 +0,0 @@ -/* This file contains non-standard modules which - * are fundamental in BBSLua framework. - */ - -/* Bitwise operations library */ -/* (c) Reuben Thomas 2000-2007 */ -/* - bitlib release 24 - ----------------- - by Reuben Thomas <rrt@sc3d.org> - http://luaforge.net/projects/bitlib - - -bitlib is a C library for Lua 5.x that provides bitwise operations. It -is copyright Reuben Thomas 2000-2007, and is released under the MIT -license, like Lua (see http://www.lua.org/copyright.html; it's -basically the same as the BSD license). There is no warranty. - -Please report bugs and make suggestions to the email address above, or -use the LuaForge trackers. - -Thanks to John Passaniti for his bitwise operations library, some of -whose ideas I used, to Shmuel Zeigerman for the test suite, to -Thatcher Ulrich for portability fixes, and to John Stiles for a bug -fix. -*/ - -#include <inttypes.h> -#include <lauxlib.h> -#include <lua.h> - -typedef int32_t Integer; -typedef uint32_t UInteger; - -#define checkUInteger(L, n) ((UInteger)luaL_checknumber((L), (n))) - -#define TDYADIC(name, op, type1, type2) \ - static int bit_ ## name(lua_State* L) { \ - lua_pushnumber(L, (Integer)((type1)checkUInteger(L, 1) op (type2)checkUInteger(L, 2))); \ - return 1; \ - } - -#define MONADIC(name, op, type) \ - static int bit_ ## name(lua_State* L) { \ - lua_pushnumber(L, (Integer)(op (type)checkUInteger(L, 1))); \ - return 1; \ - } - -#define VARIADIC(name, op, type) \ - static int bit_ ## name(lua_State *L) { \ - int n = lua_gettop(L), i; \ - Integer w = (type)checkUInteger(L, 1); \ - for (i = 2; i <= n; i++) \ - w op (type)checkUInteger(L, i); \ - lua_pushnumber(L, (Integer)w); \ - return 1; \ - } - -MONADIC(cast, +, Integer) -MONADIC(bnot, ~, Integer) -VARIADIC(band, &=, Integer) -VARIADIC(bor, |=, Integer) -VARIADIC(bxor, ^=, Integer) -TDYADIC(lshift, <<, Integer, UInteger) -TDYADIC(rshift, >>, UInteger, UInteger) -TDYADIC(arshift, >>, Integer, UInteger) - -static const struct luaL_reg bitlib[] = { - {"cast", bit_cast}, - {"bnot", bit_bnot}, - {"band", bit_band}, - {"bor", bit_bor}, - {"bxor", bit_bxor}, - {"lshift", bit_lshift}, - {"rshift", bit_rshift}, - {"arshift", bit_arshift}, - {NULL, NULL} -}; - -LUALIB_API int luaopen_bit (lua_State *L) { - luaL_openlib(L, "bit", bitlib, 0); - return 1; -} diff --git a/mbbsd/board.c b/mbbsd/board.c deleted file mode 100644 index f5cfe0de..00000000 --- a/mbbsd/board.c +++ /dev/null @@ -1,1960 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -/* personal board state - * ¬Û¹ï©ó¬ÝªOªº attr (BRD_* in ../include/pttstruct.h), - * ³o¨Ç¬O¥Î¦b user interface ªº flag */ -#define NBRD_FAV 1 -#define NBRD_BOARD 2 -#define NBRD_LINE 4 -#define NBRD_FOLDER 8 -#define NBRD_TAG 16 -#define NBRD_UNREAD 32 -#define NBRD_SYMBOLIC 64 - -#define TITLE_MATCH(bptr, key) ((key)[0] && !strcasestr((bptr)->title, (key))) - - -#define B_TOTAL(bptr) (SHM->total[(bptr)->bid - 1]) -#define B_LASTPOSTTIME(bptr) (SHM->lastposttime[(bptr)->bid - 1]) -#define B_BH(bptr) (&bcache[(bptr)->bid - 1]) - -#define HasFavEditPerm() HasUserPerm(PERM_BASIC) - -typedef struct { - int bid; - unsigned char myattr; -} __attribute__ ((packed)) boardstat_t; - -/** - * class_bid ªº·N¸q - * class_bid < 0 ¼öªù¬ÝªO - * class_bid = 0 §Úªº³Ì·R - * class_bid = 1 ¤ÀÃþ¬ÝªO - * class_bid > 1 ¨ä¥L¥Ø¿ý - */ -#define IN_HOTBOARD() (class_bid < 0) -#define IN_FAVORITE() (class_bid == 0) -#define IN_CLASSROOT() (class_bid == 1) -#define IN_SUBCLASS() (class_bid > 1) -#define IN_CLASS() (class_bid > 0) -static int class_bid = 0; - -static int nbrdsize = 0; -static boardstat_t *nbrd = NULL; -static char choose_board_depth = 0; -static int brdnum; -static char yank_flag = 1; - -static time4_t last_save_fav_and_brc; - -/* These are all the states yank_flag may be. */ -// XXX IS_LISTING_FAV() does not mean we are in favorite. -// That is controlled by IN_FAVORITE(). -#define LIST_FAV() (yank_flag = 0) -#define LIST_BRD() (yank_flag = 1) -#define IS_LISTING_FAV() (yank_flag == 0) -#define IS_LISTING_BRD() (yank_flag == 1) - -inline int getbid(const boardheader_t *fh) -{ - return (fh - bcache); -} -inline boardheader_t *getparent(const boardheader_t *fh) -{ - if(fh->parent>0) - return getbcache(fh->parent); - else - return NULL; -} - -/** - * @param[in] boardname board name, case insensitive - * @return 0 if success - * -1 if not found - * -2 permission denied - * -3 error - * @note enter board: - * 1. setup brc (currbid, currboard, currbrdattr) - * 2. set currbid, currBM, currmode, currdirect - * 3. utmp brc_id - */ -int enter_board(const char *boardname) -{ - boardheader_t *bh; - int bid; - char bname[IDLEN+1]; - char bpath[60]; - struct stat st; - - /* checking ... */ - if (boardname[0] == '\0' || !(bid = getbnum(boardname))) - return -1; - assert(0<=bid-1 && bid-1<MAX_BOARD); - bh = getbcache(bid); - if (!HasBoardPerm(bh)) - return -2; - - strlcpy(bname, bh->brdname, sizeof(bname)); - if (bname[0] == '\0') - return -3; - - setbpath(bpath, bname); - if (stat(bpath, &st) == -1) { - return -3; - } - - /* really enter board */ - brc_update(); - brc_initial_board(bname); - setutmpbid(currbid); - - set_board(); - setbdir(currdirect, currboard); - curredit &= ~EDIT_MAIL; - - return 0; -} - - -void imovefav(int old) -{ - char buf[5]; - int new; - - getdata(b_lines - 1, 0, "½Ð¿é¤J·s¦¸§Ç:", buf, sizeof(buf), DOECHO); - new = atoi(buf) - 1; - if (new < 0 || brdnum <= new){ - vmsg("¿é¤J½d³ò¦³»~!"); - return; - } - move_in_current_folder(old, new); -} - -void -init_brdbuf(void) -{ - if (brc_initialize()) - return; -} - -void -save_brdbuf(void) -{ - fav_save(); - fav_free(); -} - -int -HasBoardPerm(boardheader_t *bptr) -{ - register int level, brdattr; - - level = bptr->level; - brdattr = bptr->brdattr; - - if (HasUserPerm(PERM_SYSOP)) - return 1; - - /* ªO¥D */ - if( is_BM_cache(bptr - bcache + 1) ) /* XXXbid */ - return 1; - - /* ¯¦±K¬ÝªO¡G®Ö¹ïº®uªO¥Dªº¦n¤Í¦W³æ */ - if (brdattr & BRD_HIDE) { /* ÁôÂà */ - if (!is_hidden_board_friend((int)(bptr - bcache) + 1, currutmp->uid)) { - if (brdattr & BRD_POSTMASK) - return 0; - else - return 2; - } else - return 1; - } - - /* ¤Q¤K¸T¬ÝªO */ - if( (brdattr & BRD_OVER18) && !over18 ) - return 0; - - /* ¨î¾\ŪÅv */ - if (level && !(brdattr & BRD_POSTMASK) && !HasUserPerm(level)) - return 0; - - return 1; -} - -// board configuration utilities - -static int -b_post_note(void) -{ - char buf[200], yn[3]; - - // if(!(currmode & MODE_BOARD)) return DONOTHING; - stand_title("¦Ûqª`·N¨Æ¶µ"); - - setbfile(buf, currboard, FN_POST_NOTE); - move(b_lines-2, 0); clrtobot(); - - if (more(buf, NA) == -1) - more("etc/" FN_POST_NOTE, NA); - getdata(b_lines - 2, 0, "¬O§_n¥Î¦Ûqµo¤åª`·N¨Æ¶µ? [y/N]", - yn, sizeof(yn), LCECHO); - if (yn[0] == 'y') - vedit(buf, NA, NULL); - else - unlink(buf); - - setbfile(buf, currboard, FN_POST_BID); - if (more(buf, NA) == -1) - more("etc/" FN_POST_BID, NA); - getdata(b_lines - 2, 0, "¬O§_n¥Î¦ÛqÄv¼Ð¤å³¹ª`·N¨Æ¶µ? [y/N]", - yn, sizeof(yn), LCECHO); - if (yn[0] == 'y') - vedit(buf, NA, NULL); - else - unlink(buf); - - return FULLUPDATE; -} - -static int -b_posttype() -{ - boardheader_t *bp; - int i, aborted; - char filepath[PATHLEN], genbuf[60], title[5], posttype_f, posttype[33]=""; - - // if(!(currmode & MODE_BOARD)) return DONOTHING; - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - stand_title("³]©w¤å³¹Ãþ§O"); - - move(2,0); - clrtobot(); - posttype_f = bp->posttype_f; - for( i = 0 ; i < 8 ; ++i ){ - move(2+i,0); - outs("¤å³¹ºØÃþ: "); - strlcpy(genbuf, bp->posttype + i * 4, 5); - sprintf(title, "%d.", i + 1); - if( !getdata_buf(2+i, 11, title, genbuf, 5, DOECHO) ) - break; - sprintf(posttype + i * 4, "%-4.4s", genbuf); - if( posttype_f & (1<<i) ){ - if( getdata(2+i, 20, "³]©w½d¥»®æ¦¡¡H(Y/n)", genbuf, 3, LCECHO) && - genbuf[0]=='n' ){ - posttype_f &= ~(1<<i); - continue; - } - } - else if ( !getdata(2+i, 20, "³]©w½d¥»®æ¦¡¡H(y/N)", genbuf, 3, LCECHO) || - genbuf[0] != 'y' ) - continue; - - setbnfile(filepath, bp->brdname, "postsample", i); - aborted = vedit(filepath, NA, NULL); - if (aborted == -1) { - clear(); - posttype_f &= ~(1<<i); - continue; - } - posttype_f |= (1<<i); - } - bp->posttype_f = posttype_f; - strlcpy(bp->posttype, posttype, sizeof(bp->posttype)); /* ³oÃäÀ³¸Ón¨¾race condition */ - - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); - return FULLUPDATE; -} - -// integrated board config -int -b_config(void) -{ - boardheader_t *bp=NULL; - int touched = 0, finished = 0; - bp = getbcache(currbid); - int i = 0, attr = 0, ipostres; - char isBM = (currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP); - -#define LNBOARDINFO (17) -#define LNPOSTRES (12) -#define COLPOSTRES (50) - - int ytitle = b_lines - LNBOARDINFO; - -#ifdef OLDRECOMMEND - ytitle ++; -#endif // OLDRECOMMEND - - grayout(0, ytitle-2, GRAYOUT_DARK); - - // available hotkeys yet: - // a b d j k p q z - // 2 3 4 5 6 7 9 - // better not: l 0 - - while(!finished) { - move(ytitle-1, 0); clrtobot(); - // outs(MSG_SEPERATOR); // deprecated by grayout - move(ytitle, 0); - outs(ANSI_COLOR(7) " " ); outs(bp->brdname); outs(" ¬ÝªO³]©w"); - i = t_columns - strlen(bp->brdname) - strlen(" ¬ÝªO³]©w") - 2; - for (; i>0; i--) - outc(' '); - outs(ANSI_RESET); - - move(ytitle +2, 0); - clrtobot(); - - prints(" ¤¤¤å±Ôz: %s\n", bp->title); - prints(" ªO¥D¦W³æ: %s\n", (bp->BM[0] > ' ')? bp->BM : "(µL)"); - - outs(" \n"); // at least one character, for move_ansi. - - prints( " " ANSI_COLOR(1;36) "h" ANSI_RESET - " - ¤½¶}ª¬ºA(¬O§_Áô§Î): %s " ANSI_RESET "\n", - (bp->brdattr & BRD_HIDE) ? - ANSI_COLOR(1)"Áô§Î":"¤½¶}"); - - prints( " " ANSI_COLOR(1;36) "g" ANSI_RESET - " - ÁôªO®É %s ¶i¤J¤Q¤j±Æ¦æº]" ANSI_RESET "\n", - (bp->brdattr & BRD_BMCOUNT) ? - ANSI_COLOR(1)"¥i¥H" ANSI_RESET: - "¤£¥i"); - - prints( " " ANSI_COLOR(1;36) "r" ANSI_RESET - " - %s " ANSI_RESET "±ÀÂˤ峹\n", - (bp->brdattr & BRD_NORECOMMEND) ? - ANSI_COLOR(31)"¤£¥i":"¥i¥H"); - -#ifndef OLDRECOMMEND - prints( " " ANSI_COLOR(1;36) "b" ANSI_RESET - " - %s " ANSI_RESET "¼N¤å\n", - ((bp->brdattr & BRD_NORECOMMEND) || (bp->brdattr & BRD_NOBOO)) - ? ANSI_COLOR(1)"¤£¥i":"¥i¥H"); -#endif - { - int d = 0; - - if(bp->brdattr & BRD_NORECOMMEND) - { - d = -1; - } else { - if ((bp->brdattr & BRD_NOFASTRECMD) && - (bp->fastrecommend_pause > 0)) - d = bp->fastrecommend_pause; - } - - prints( " " ANSI_COLOR(1;36) "f" ANSI_RESET - " - %s " ANSI_RESET "§Ö³t³s±À¤å³¹", - d != 0 ? - ANSI_COLOR(1)"¨î": "¥i¥H"); - if(d > 0) - prints(", ³Ì§C¶¡¹j®É¶¡: %d ¬í", d); - outs("\n"); - } - - prints( " " ANSI_COLOR(1;36) "i" ANSI_RESET - " - ±À¤å®É %s" ANSI_RESET " °O¿ý¨Ó·½ IP\n", - (bp->brdattr & BRD_IPLOGRECMD) ? - ANSI_COLOR(1)"n":"¤£¥Î"); - -#ifdef USE_AUTOCPLOG - prints( " " ANSI_COLOR(1;36) "x" ANSI_RESET - " - Âà¿ý¤å³¹ %s " ANSI_RESET "¦Û°Ê°O¿ý¡A¥B %s " - ANSI_RESET "µo¤åÅv\n", - (bp->brdattr & BRD_CPLOG) ? - ANSI_COLOR(1)"·|" : "¤£·|" , - (bp->brdattr & BRD_CPLOG) ? - ANSI_COLOR(1)"»Ýn" : "¤£»Ý" - ); -#endif - - prints( " " ANSI_COLOR(1;36) "L" ANSI_RESET - " - Y¦³Âà«H«hµo¤å®É¹w³] %s " ANSI_RESET "\n", - (bp->brdattr & BRD_LOCALSAVE) ? - "¯¸¤º¦sÀÉ(¤£Âà¥X)" : ANSI_COLOR(1)"¯¸»Ú¦sÀÉ(Âà¥X)" ); - - // use '8' instead of '1', to prevent 'l'/'1' confusion - prints( " " ANSI_COLOR(1;36) "8" ANSI_RESET - " - ¥¼º¡¤Q¤K·³ %s " ANSI_RESET - "¶i¤J\n", (bp->brdattr & BRD_OVER18) ? - ANSI_COLOR(1) "¤£¥i¥H" : "¥i¥H" ); - - prints( " " ANSI_COLOR(1;36) "y" ANSI_RESET - " - %s" ANSI_RESET - " ¦^¤å\n", - (bp->brdattr & BRD_NOREPLY) ? - ANSI_COLOR(1)"¤£¥i¥H" : "¥i¥H" ); - - prints( " " ANSI_COLOR(1;36) "e" ANSI_RESET - " - µo¤åÅv: %s" ANSI_RESET "\n", - (bp->brdattr & BRD_RESTRICTEDPOST) ? - ANSI_COLOR(1)"¥u¦³ªO¤Í¤~¥iµo¤å" : "µL¯S§O³]©w" ); - - ipostres = b_lines - LNPOSTRES; - move_ansi(ipostres++, COLPOSTRES-2); - - if (CheckPostPerm() && CheckPostRestriction(currbid)) - outs(ANSI_COLOR(1;32)); - else - outs(ANSI_COLOR(1;31)); - outs("µo¤å»P±À¤å¨î" ANSI_RESET); - -#define POSTRESTRICTION(msg,utag) \ - prints(msg, attr ? ANSI_COLOR(1) : "", i, attr ? ANSI_RESET : "") - - if (bp->post_limit_logins) - { - move_ansi(ipostres++, COLPOSTRES); - i = (int)bp->post_limit_logins * 10; - attr = (cuser.numlogins < i) ? 1 : 0; - if (attr) outs(ANSI_COLOR(31)); - prints("¤W¯¸¦¸¼Æ %d ¦¸¥H¤W", i); - if (attr) outs(ANSI_RESET); - } - - if (bp->post_limit_posts) - { - move_ansi(ipostres++, COLPOSTRES); - i = (int)bp->post_limit_posts * 10; - attr = (cuser.numposts < i) ? 1 : 0; - if (attr) outs(ANSI_COLOR(31)); - prints("¤å³¹½g¼Æ %d ½g¥H¤W", i); - if (attr) outs(ANSI_RESET); - } - - if (bp->post_limit_regtime) - { - move_ansi(ipostres++, COLPOSTRES); - i = bp->post_limit_regtime; - attr = (cuser.firstlogin > - (now - (time4_t)bp->post_limit_regtime * 2592000)) ? 1 : 0; - if (attr) outs(ANSI_COLOR(31)); - prints("µù¥U®É¶¡ %d Ó¤ë¥H¤W",i); - if (attr) outs(ANSI_RESET); - } - - // if (bp->post_limit_badpost) - { - move_ansi(ipostres++, COLPOSTRES); - i = 255 - bp->post_limit_badpost; - attr = (cuser.badpost > i) ? 1 : 0; - if (attr) outs(ANSI_COLOR(31)); - prints("¦H¤å½g¼Æ %d ½g¥H¤U", i); - if (attr) outs(ANSI_RESET); - } - - if (!CheckPostPerm()) - { - const char *msg = postperm_msg(bp->brdname); - if (msg) // some reasons - { - move_ansi(ipostres++, COLPOSTRES); - outs(ANSI_COLOR(1;31)); - outs(msg); - outs(ANSI_RESET); - } - } - - // show BM commands - { - const char *aCat = ANSI_COLOR(1;32); - const char *aHot = ANSI_COLOR(1;36); - const char *aRst = ANSI_RESET; - - if (!isBM) - { - aCat = ANSI_COLOR(1;30;40); - aHot = ""; - aRst = ""; - } - - ipostres ++; - move_ansi(ipostres++, COLPOSTRES-2); - outs(aCat); - outs("¦W³æ½s¿è»P¨ä¥¦:"); - if (!isBM) outs(" (»ÝªO¥DÅv)"); - outs(aRst); - move_ansi(ipostres++, COLPOSTRES); - prints("%sv%s)¥i¨£¦W³æ %sw%s)¤ô±í¦W³æ ", - aHot, aRst, aHot, aRst); - move_ansi(ipostres++, COLPOSTRES); - prints("%sm%s)Á|¿ì§ë²¼ %so%s)§ë²¼¦W³æ ", - aHot, aRst, aHot, aRst); - move_ansi(ipostres++, COLPOSTRES); - prints("%sc%s)¤å³¹Ãþ§O %sn%s)µo¤åª`·N¨Æ¶µ ", - aHot, aRst, aHot, aRst); - outs(ANSI_RESET); - } - - move(b_lines, 0); - if (!isBM) - { - vmsg("±z¹ï¦¹ªOµLºÞ²zÅv"); - return FULLUPDATE; - } - - switch(tolower(getans("½Ð¿é¤Jn§ïÅܪº³]©w, ¨ä¥¦Áäµ²§ô: "))) - { -#ifdef USE_AUTOCPLOG - case 'x': - bp->brdattr ^= BRD_CPLOG; - touched = 1; - break; -#endif - case 'l': - bp->brdattr ^= BRD_LOCALSAVE; - touched = 1; - break; - - case 'e': - if(HasUserPerm(PERM_SYSOP)) - { - bp->brdattr ^= BRD_RESTRICTEDPOST; - touched = 1; - } else { - vmsg("¦¹¶µ³]©w»Ýn¯¸ªøÅv"); - } - break; - - case 'h': -#ifndef BMCHS - if (!HasUserPerm(PERM_SYSOP)) - { - vmsg("¦¹¶µ³]©w»Ýn¯¸ªøÅv"); - break; - } -#endif - if(bp->brdattr & BRD_HIDE) - { - bp->brdattr &= ~BRD_HIDE; - bp->brdattr &= ~BRD_POSTMASK; - hbflreload(currbid); - } else { - bp->brdattr |= BRD_HIDE; - bp->brdattr |= BRD_POSTMASK; - } - touched = 1; - break; - - case 'g': -#ifndef BMCHS - if (!HasUserPerm(PERM_SYSOP)) - { - vmsg("¦¹¶µ³]©w»Ýn¯¸ªøÅv"); - break; - } -#endif - bp->brdattr ^= BRD_BMCOUNT; - touched = 1; - break; - - case 'r': - bp->brdattr ^= BRD_NORECOMMEND; - touched = 1; - break; - - case 'i': - bp->brdattr ^= BRD_IPLOGRECMD; - touched = 1; - break; - - case 'f': - bp->brdattr &= ~BRD_NORECOMMEND; - bp->brdattr ^= BRD_NOFASTRECMD; - touched = 1; - - if(bp->brdattr & BRD_NOFASTRECMD) - { - char buf[8] = ""; - - if(bp->fastrecommend_pause > 0) - sprintf(buf, "%d", bp->fastrecommend_pause); - getdata_str(b_lines-1, 0, - "½Ð¿é¤J³s±À®É¶¡¨î(³æ¦ì: ¬í) [5~240]: ", - buf, 4, ECHO, buf); - if(buf[0] >= '0' && buf[0] <= '9') - bp->fastrecommend_pause = atoi(buf); - - if( bp->fastrecommend_pause < 5 || - bp->fastrecommend_pause > 240) - { - if(buf[0]) - { - vmsg("¿é¤J®É¶¡µL®Ä¡A½Ð¨Ï¥Î 5~240 ¤§¶¡ªº¼Æ¦r¡C"); - } - bp->fastrecommend_pause = 0; - bp->brdattr &= ~BRD_NOFASTRECMD; - } - } - break; -#ifndef OLDRECOMMEND - case 'b': - if(bp->brdattr & BRD_NORECOMMEND) - bp->brdattr |= BRD_NOBOO; - bp->brdattr ^= BRD_NOBOO; - touched = 1; - if (!(bp->brdattr & BRD_NOBOO)) - bp->brdattr &= ~BRD_NORECOMMEND; - break; -#endif - case '8': - if (!over18) - { - vmsg("ªO¥D¥»¨¥¼º¡ 18 ·³¡C"); - } else { - bp->brdattr ^= BRD_OVER18; - touched = 1; - } - break; - - case 'v': - clear(); - friend_edit(BOARD_VISABLE); - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - hbflreload(currbid); - clear(); - break; - - case 'w': - clear(); - friend_edit(BOARD_WATER); - clear(); - break; - - case 'o': - clear(); - friend_edit(FRIEND_CANVOTE); - clear(); - - case 'm': - clear(); - b_vote_maintain(); - clear(); - break; - - case 'n': - clear(); - b_post_note(); - clear(); - break; - - case 'c': - clear(); - b_posttype(); - clear(); - break; - - case 'y': - if (!(HasUserPerm(PERM_SYSOP) || (HasUserPerm(PERM_SYSSUPERSUBOP) && GROUPOP()) ) ) { - vmsg("¦¹¶µ³]©w»Ýn¸s²Õªø©Î¯¸ªøÅv"); - break; - } - bp->brdattr ^= BRD_NOREPLY; - touched = 1; - break; - - default: - finished = 1; - break; - } - } - if(touched) - { - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); - log_usies("SetBoard", bp->brdname); - vmsg("¤wÀx¦s·s³]©w"); - } - else - vmsg("¥¼§ïÅÜ¥ô¦ó³]©w"); - - return FULLUPDATE; -} - -static int -check_newpost(boardstat_t * ptr) -{ /* Ptt §ï */ - time4_t ftime; - - ptr->myattr &= ~NBRD_UNREAD; - if (B_BH(ptr)->brdattr & (BRD_GROUPBOARD | BRD_SYMBOLIC)) - return 0; - - if (B_TOTAL(ptr) == 0) - { - setbtotal(ptr->bid); - setbottomtotal(ptr->bid); - } - if (B_TOTAL(ptr) == 0) - return 0; - ftime = B_LASTPOSTTIME(ptr); - - /* ¦³¨Ç util, ¤×¨ä¬O innbbsd, ·|¥Î¨ì¤ñ¸û·sªº time stamp, - * ¥un¤£¤Ó¸Ø±i´N ok */ - if (ftime > now + 10) - ftime = B_LASTPOSTTIME(ptr) = now - 1; - - if ( brc_unread_time(ptr->bid, ftime, 0) ) - ptr->myattr |= NBRD_UNREAD; - - return 1; -} - -static void -load_uidofgid(const int gid, const int type) -{ - boardheader_t *bptr, *currbptr, *parent; - int bid, n, childcount = 0; - assert(0<=type && type<2); - assert(0<= gid-1 && gid-1<MAX_BOARD); - currbptr = parent = &bcache[gid - 1]; - assert(0<=numboards && numboards<=MAX_BOARD); - for (n = 0; n < numboards; ++n) { - bid = SHM->bsorted[type][n]+1; - if( bid<=0 || !(bptr = getbcache(bid)) - || bptr->brdname[0] == '\0' ) - continue; - if (bptr->gid == gid) { - if (currbptr == parent) - currbptr->firstchild[type] = bid; - else { - currbptr->next[type] = bid; - currbptr->parent = gid; - } - childcount++; - currbptr = bptr; - } - } - parent->childcount = childcount; - if (currbptr == parent) // no child - currbptr->firstchild[type] = -1; - else // the last child - currbptr->next[type] = -1; -} - -static boardstat_t * -addnewbrdstat(int n, int state) -{ - boardstat_t *ptr; - - // ptt 2 local modification - // XXX maybe some developer discovered signed short issue? - assert(n != -32769); - - assert(0<=n && n<MAX_BOARD); - assert(0<=brdnum && brdnum<nbrdsize); - ptr = &nbrd[brdnum++]; - //boardheader_t *bptr = &bcache[n]; - //ptr->total = &(SHM->total[n]); - //ptr->lastposttime = &(SHM->lastposttime[n]); - - ptr->bid = n + 1; - ptr->myattr = state; - if ((B_BH(ptr)->brdattr & BRD_HIDE) && state == NBRD_BOARD) - B_BH(ptr)->brdattr |= BRD_POSTMASK; - if (!IS_LISTING_FAV()) - ptr->myattr &= ~NBRD_FAV; - check_newpost(ptr); - return ptr; -} - -#if !HOTBOARDCACHE -static int -cmpboardfriends(const void *brd, const void *tmp) -{ -#ifdef USE_COOLDOWN - if ((B_BH((boardstat_t*)tmp)->brdattr & BRD_COOLDOWN) && - (B_BH((boardstat_t*)brd)->brdattr & BRD_COOLDOWN)) - return 0; - else if ( B_BH((boardstat_t*)tmp)->brdattr & BRD_COOLDOWN ) { - if (B_BH((boardstat_t*)brd)->nuser == 0) - return 0; - else - return 1; - } - else if ( B_BH((boardstat_t*)brd)->brdattr & BRD_COOLDOWN ) { - if (B_BH((boardstat_t*)tmp)->nuser == 0) - return 0; - else - return -1; - } -#endif - return ((B_BH((boardstat_t*)tmp)->nuser) - - (B_BH((boardstat_t*)brd)->nuser)); -} -#endif - -static void -load_boards(char *key) -{ - int type = cuser.uflag & BRDSORT_FLAG ? 1 : 0; - int i; - int state; - - brdnum = 0; - if (nbrd) { - free(nbrd); - nbrdsize = 0; - nbrd = NULL; - } - if (!IN_CLASS()) { - if(IS_LISTING_FAV()){ - fav_t *fav = get_current_fav(); - int nfav = get_data_number(fav); - if( nfav == 0 ) { - nbrdsize = 1; - nbrd = (boardstat_t *)malloc(sizeof(boardstat_t) * 1); - addnewbrdstat(0, 0); // dummy - return; - } - nbrdsize = nfav; - nbrd = (boardstat_t *)malloc(sizeof(boardstat_t) * nfav); - for( i = 0 ; i < fav->DataTail; ++i ){ - int state; - if (!(fav->favh[i].attr & FAVH_FAV)) - continue; - - if ( !key[0] ){ - if (get_item_type(&fav->favh[i]) == FAVT_LINE ) - state = NBRD_LINE; - else if (get_item_type(&fav->favh[i]) == FAVT_FOLDER ) - state = NBRD_FOLDER; - else { - state = NBRD_BOARD; - if (is_set_attr(&fav->favh[i], FAVH_UNREAD)) - state |= NBRD_UNREAD; - } - } else { - if (get_item_type(&fav->favh[i]) == FAVT_LINE ) - continue; - else if (get_item_type(&fav->favh[i]) == FAVT_FOLDER ){ - if( strcasestr( - get_folder_title(fav_getid(&fav->favh[i])), - key) - ) - state = NBRD_FOLDER; - else - continue; - }else{ - boardheader_t *bptr = getbcache(fav_getid(&fav->favh[i])); - assert(0<=fav_getid(&fav->favh[i])-1 && fav_getid(&fav->favh[i])-1<MAX_BOARD); - if (strcasestr(bptr->title, key)) - state = NBRD_BOARD; - else - continue; - if (is_set_attr(&fav->favh[i], FAVH_UNREAD)) - state |= NBRD_UNREAD; - } - } - - if (is_set_attr(&fav->favh[i], FAVH_TAG)) - state |= NBRD_TAG; - if (is_set_attr(&fav->favh[i], FAVH_ADM_TAG)) - state |= NBRD_TAG; - // ¦³¨Ç¤H ¬Y¨Ç bid < 0 Orzz // ptt2 local modification - if (fav_getid(&fav->favh[i]) < 1) - continue; - addnewbrdstat(fav_getid(&fav->favh[i]) - 1, NBRD_FAV | state); - } - } -#if HOTBOARDCACHE - else if(IN_HOTBOARD()){ - nbrdsize = SHM->nHOTs; - if(nbrdsize == 0) { - nbrdsize = 1; - nbrd = (boardstat_t *)malloc(sizeof(boardstat_t) * 1); - addnewbrdstat(0, 0); // dummy - return; - } - assert(0<nbrdsize); - nbrd = (boardstat_t *)malloc(sizeof(boardstat_t) * nbrdsize); - for( i = 0 ; i < nbrdsize; ++i ) { - if(SHM->HBcache[i] == -1) - continue; - addnewbrdstat(SHM->HBcache[i], HasBoardPerm(&bcache[SHM->HBcache[i]])); - } - } -#endif - else { // general case - nbrdsize = numboards; - assert(0<nbrdsize && nbrdsize<=MAX_BOARD); - nbrd = (boardstat_t *) malloc(sizeof(boardstat_t) * nbrdsize); - for (i = 0; i < nbrdsize; i++) { - int n = SHM->bsorted[type][i]; - boardheader_t *bptr; - if (n < 0) - continue; - bptr = &bcache[n]; - if (bptr == NULL) - continue; - if (!bptr->brdname[0] || - (bptr->brdattr & (BRD_GROUPBOARD | BRD_SYMBOLIC)) || - !((state = HasBoardPerm(bptr)) || GROUPOP()) || - TITLE_MATCH(bptr, key) -#if ! HOTBOARDCACHE - || (IN_HOTBOARD() && bptr->nuser < 5) -#endif - ) - continue; - addnewbrdstat(n, state); - } - } -#if ! HOTBOARDCACHE - if (IN_HOTBOARD()) - qsort(nbrd, brdnum, sizeof(boardstat_t), cmpboardfriends); -#endif - } else { /* load boards of a subclass */ - boardheader_t *bptr = getbcache(class_bid); - int childcount; - int bid; - - assert(0<=class_bid-1 && class_bid-1<MAX_BOARD); - if (bptr->firstchild[type] == 0 || bptr->childcount==0) - load_uidofgid(class_bid, type); - - childcount = bptr->childcount; // Ptt: child count after load_uidofgid - - nbrdsize = childcount + 5; - nbrd = (boardstat_t *) malloc((childcount+5) * sizeof(boardstat_t)); - // ¹w¯d¨âÓ¥H§K¤j¶q¶}ªO®É±¾½Õ - for (bid = bptr->firstchild[type]; bid > 0 && - brdnum < childcount+5; bid = bptr->next[type]) { - assert(0<=bid-1 && bid-1<MAX_BOARD); - bptr = getbcache(bid); - state = HasBoardPerm(bptr); - if ( !(state || GROUPOP()) || TITLE_MATCH(bptr, key) ) - continue; - - if (bptr->brdattr & BRD_SYMBOLIC) { - /* Only SYSOP knows a board is symbolic */ - if (HasUserPerm(PERM_SYSOP) || HasUserPerm(PERM_SYSSUPERSUBOP)) - state |= NBRD_SYMBOLIC; - else { - bid = BRD_LINK_TARGET(bptr); - if (bcache[bid - 1].brdname[0] == 0) { - vmsg("³sµ²¤w·l·´¡A½Ð¦Ü SYSOP ¦^³ø¦¹°ÝÃD¡C"); - continue; - } - } - } - assert(0<=bid-1 && bid-1<MAX_BOARD); - addnewbrdstat(bid-1, state); - } - if(childcount < brdnum) { - //Ptt: dirty fix fix soon - getbcache(class_bid)->childcount = 0; - } - - - } -} - -static int -search_board(void) -{ - int num; - char genbuf[IDLEN + 2]; - struct NameList namelist; - - move(0, 0); - clrtoeol(); - NameList_init(&namelist); - assert(brdnum<=nbrdsize); - NameList_resizefor(&namelist, brdnum); - for (num = 0; num < brdnum; num++) - if (!IS_LISTING_FAV() || - (nbrd[num].myattr & NBRD_BOARD && HasBoardPerm(B_BH(&nbrd[num]))) ) - NameList_add(&namelist, B_BH(&nbrd[num])->brdname); - namecomplete2(&namelist, MSG_SELECT_BOARD, genbuf); - NameList_delete(&namelist); - -#ifdef DEBUG - vmsg(genbuf); -#endif - - for (num = 0; num < brdnum; num++) - if (!strcasecmp(B_BH(&nbrd[num])->brdname, genbuf)) - return num; - return -1; -} - -static int -unread_position(char *dirfile, boardstat_t * ptr) -{ - fileheader_t fh; - char fname[FNLEN]; - register int num, fd, step, total; - - total = B_TOTAL(ptr); - num = total + 1; - if ((ptr->myattr & NBRD_UNREAD) && (fd = open(dirfile, O_RDWR)) > 0) { - if (!brc_initial_board(B_BH(ptr)->brdname)) { - num = 1; - } else { - num = total - 1; - step = 4; - while (num > 0) { - lseek(fd, (off_t) (num * sizeof(fh)), SEEK_SET); - if (read(fd, fname, FNLEN) <= 0 || - !brc_unread(ptr->bid, fname, 0)) - break; - num -= step; - if (step < 32) - step += step >> 1; - } - if (num < 0) - num = 0; - while (num < total) { - lseek(fd, (off_t) (num * sizeof(fh)), SEEK_SET); - if (read(fd, fname, FNLEN) <= 0 || - brc_unread(ptr->bid, fname, 0)) - break; - num++; - } - } - close(fd); - } - if (num < 0) - num = 0; - return num; -} - -static char -get_fav_type(boardstat_t *ptr) -{ - if (ptr->myattr & NBRD_FOLDER) - return FAVT_FOLDER; - else if (ptr->myattr & NBRD_BOARD) - return FAVT_BOARD; - else if (ptr->myattr & NBRD_LINE) - return FAVT_LINE; - return 0; -} - -static void -brdlist_foot(void) -{ - outs( ANSI_COLOR(34;46) " ¿ï¾Ü¬ÝªO " - ANSI_COLOR(31;47) " (c)" ANSI_COLOR(30) "·s¤å³¹¼Ò¦¡ " - ANSI_COLOR(31) "(v/V)" ANSI_COLOR(30) "¼Ð¬°¤wŪ/¥¼Åª " - ANSI_COLOR(31) "(y)" ANSI_COLOR(30)); - if(IS_LISTING_FAV()) - outs("¦C¥X¥þ³¡"); - else if (IS_LISTING_BRD()) - outs("¿z¿ï¦Cªí"); - else outs("¿z¿ï¦Cªí"); // never reach here? - - outslr(" " ANSI_COLOR(31) "(m)" ANSI_COLOR(30) "¤Á´«³Ì·R", - 73, ANSI_RESET, 0); -} - - -static inline char * -make_class_color(char *name) -{ - /* 34 is too dark */ - char *colorset[8] = {"", ANSI_COLOR(32), - ANSI_COLOR(33), ANSI_COLOR(36), ANSI_COLOR(1;34), - ANSI_COLOR(1), ANSI_COLOR(1;32), ANSI_COLOR(1;33)}; - - return colorset[(unsigned int) - (name[0] + name[1] + - name[2] + name[3]) & 0x7]; -} - -#define HILIGHT_COLOR ANSI_COLOR(1;36) - -static void -show_brdlist(int head, int clsflag, int newflag) -{ - int myrow = 2; - if (unlikely(IN_CLASSROOT())) { - currstat = CLASS; - myrow = 6; - showtitle("¤ÀÃþ¬ÝªO", BBSName); - movie(0); - move(1, 0); - // TODO remove ascii art here - outs( - " " - "¢© ¢~¡X" ANSI_COLOR(33) "¡´\n" - " ùá¡X " ANSI_RESET " " - "¢¨¢i" ANSI_COLOR(47) "¡ó" ANSI_COLOR(40) "¢i¢i¢©ùç\n" - " " ANSI_COLOR(44) " ¡s¡s¡s¡s¡s¡s¡s¡s " - ANSI_COLOR(33) "ùø" ANSI_RESET ANSI_COLOR(44) " ¢©¢¨¢i¢i¢i¡¿¡¿¡¿ùø " ANSI_RESET "\n" - " " ANSI_COLOR(44) " " - ANSI_COLOR(33) " " ANSI_RESET ANSI_COLOR(44) " ¢«¢ª¢i¢i¢i¡¶¡¶¡¶ ùø" ANSI_RESET "\n" - " ¡s¡s¡s¡s¡s¡s¡s¡s " ANSI_COLOR(33) - "¢x" ANSI_RESET " ¢ª¢i¢i¢i¢i¢« ùø\n" - " " ANSI_COLOR(33) "ùó" - "¡X¡X" ANSI_RESET " ¢« ¡X¡Ï" ANSI_RESET); - } else if (clsflag) { - showtitle("¬ÝªO¦Cªí", BBSName); - // [m]¥[¤J©Î²¾¥X§Úªº³Ì·R - outs("[¡ö][q]¥D¿ï³æ [¡÷][r]¾\\Ū [¡ô¡õ]¿ï¾Ü [PgUp][PgDn]½¶ [S]±Æ§Ç [/]·j´M [h]¨D§U\n"); - outs(ANSI_COLOR(7)); - - // boards in Ptt series are very, very large. - // let's create more space for board numbers, - // and less space for BM. - // - // newflag is not so different now because we use all 5 digits. - - outs( newflag ? " Á`¼Æ" : " ½s¸¹"); - outs(" ¬Ý ªO Ãþ§O Âà«H ¤¤ ¤å ±Ô z ¤H®ð ªO ¥D"); - outslr("", 74, ANSI_RESET, 0); - move(b_lines, 0); - brdlist_foot(); - } - if (brdnum > 0) { - boardstat_t *ptr; - char *unread[2] = {ANSI_COLOR(37) " " ANSI_RESET, ANSI_COLOR(1;31) "£¾" ANSI_RESET}; - - if (IS_LISTING_FAV() && brdnum == 1 && get_fav_type(&nbrd[0]) == 0) { - - // (a) or (i) needs HasUserPerm(PERM_LOGINOK)). - // 3 = first line of empty area - if (!HasFavEditPerm()) - { - // TODO actually we cannot use 's' (for PTT)... - mouts(3, 10, - "--- µù¥Uªº¨Ï¥ÎªÌ¤~¯à·s¼W¬ÝªO³á (¥i«ö s ¤â°Ê¿ï¨ú) ---"); - } else { - // normal user. tell him what to do. - mouts(3, 10, - "--- ªÅ¥Ø¿ý¡A½Ð«ö a ·s¼W©Î¥Î y ¦C¥X¥þ³¡¬ÝªO«á«ö z ¼W§R ---"); - } - return; - } - - while (++myrow < b_lines) { - - move(myrow, 0); - clrtoeol(); - - if (head < brdnum) { - assert(0<=head && head<nbrdsize); - ptr = &nbrd[head++]; - if (ptr->myattr & NBRD_LINE){ - if( !newflag ) - prints("%7d %c ", head, ptr->myattr & NBRD_TAG ? 'D' : ' '); - else - prints("%7s ", ""); - - if (!(ptr->myattr & NBRD_FAV)) - outs(ANSI_COLOR(1;30)); - - outs("------------" - " " - // "------" - "------------------------------------------" - ANSI_RESET "\n"); - continue; - } - else if (ptr->myattr & NBRD_FOLDER){ - char *title = get_folder_title(ptr->bid); - prints("%7d %c ", - newflag ? - get_data_number(get_fav_folder(getfolder(ptr->bid))) : - head, ptr->myattr & NBRD_TAG ? 'D' : ' '); - - // well, what to print with myfav folders? - // this style is too long and we don't want to - // fight with users... - // think about new way some otherday. - prints("%sMyFavFolder" ANSI_RESET " ¥Ø¿ý ¡¼%-34s", - !(cuser.uflag2 & FAVNOHILIGHT)?HILIGHT_COLOR : "", - title); - /* - if (!(cuser.uflag2 & FAVNOHILIGHT)) - outs(HILIGHT_COLOR); - prints("%-12s", "[Folder]"); - outs(ANSI_RESET); - prints(" ¥Ø¿ý £U%-34s", title); - */ - /* - outs(ANSI_COLOR(0;36)); - prints("£U%-70.70s", title); - outs(ANSI_RESET); - */ - continue; - } - - if (IN_CLASSROOT()) - outs(" "); - else { - if (!GROUPOP() && !HasBoardPerm(B_BH(ptr))) { - if (newflag) prints("%7s", ""); - else prints("%7d", head); - prints(" %c Unknown?? ÁôªO ¡H³oÓªO¬OÁôªO", - ptr->myattr & NBRD_TAG ? 'D' : ' '); - continue; - } - } - - if (newflag && B_BH(ptr)->brdattr & BRD_GROUPBOARD) - outs(" "); - else - prints("%7d%c%s", - newflag ? (int)(B_TOTAL(ptr)) : head, - !(B_BH(ptr)->brdattr & BRD_HIDE) ? ' ' : - (B_BH(ptr)->brdattr & BRD_POSTMASK) ? ')' : '-', - (ptr->myattr & NBRD_TAG) ? "D " : - (B_BH(ptr)->brdattr & BRD_GROUPBOARD) ? " " : - unread[ptr->myattr & NBRD_UNREAD ? 1 : 0]); - - if (!IN_CLASSROOT()) { - prints("%s%-13s" ANSI_RESET "%s%5.5s" ANSI_COLOR(0;37) - "%2.2s" ANSI_RESET "%-34.34s", - ((!(cuser.uflag2 & FAVNOHILIGHT) && - getboard(ptr->bid) != NULL))? HILIGHT_COLOR : "", - B_BH(ptr)->brdname, - make_class_color(B_BH(ptr)->title), - B_BH(ptr)->title, B_BH(ptr)->title + 5, B_BH(ptr)->title + 7); - -#ifdef USE_COOLDOWN - if (B_BH(ptr)->brdattr & BRD_COOLDOWN) - outs("ÀR "); - else if (B_BH(ptr)->brdattr & BRD_BAD) -#else - if (B_BH(ptr)->brdattr & BRD_BAD) -#endif - outs(" X "); - - else if (B_BH(ptr)->nuser <= 0) - prints(" %c ", B_BH(ptr)->bvote ? 'V' : ' '); - else if (B_BH(ptr)->nuser <= 10) - prints("%2d ", B_BH(ptr)->nuser); - else if (B_BH(ptr)->nuser <= 50) - prints(ANSI_COLOR(1;33) "%2d" ANSI_RESET " ", B_BH(ptr)->nuser); -#ifdef EXTRA_HOTBOARD_COLORS - // piaip 2008/02/04: new colors - else if (B_BH(ptr)->nuser >= 100000) - outs(ANSI_COLOR(1;35) "Ãz!" ANSI_RESET); - else if (B_BH(ptr)->nuser >= 60000) - outs(ANSI_COLOR(1;33) "Ãz!" ANSI_RESET); - else if (B_BH(ptr)->nuser >= 30000) - outs(ANSI_COLOR(1;32) "Ãz!" ANSI_RESET); - else if (B_BH(ptr)->nuser >= 10000) - outs(ANSI_COLOR(1;36) "Ãz!" ANSI_RESET); -#endif - else if (B_BH(ptr)->nuser >= 5000) - outs(ANSI_COLOR(1;34) "Ãz!" ANSI_RESET); - else if (B_BH(ptr)->nuser >= 2000) - outs(ANSI_COLOR(1;31) "Ãz!" ANSI_RESET); - else if (B_BH(ptr)->nuser >= 1000) - outs(ANSI_COLOR(1) "Ãz!" ANSI_RESET); - else if (B_BH(ptr)->nuser >= 100) - outs(ANSI_COLOR(1) "HOT" ANSI_RESET); - else //if (B_BH(ptr)->nuser > 50) - prints(ANSI_COLOR(1;31) "%2d" ANSI_RESET " ", B_BH(ptr)->nuser); - prints("%.*s" ANSI_CLRTOEND, t_columns - 68, B_BH(ptr)->BM); - } else { - prints("%-40.40s %.*s", B_BH(ptr)->title + 7, - t_columns - 68, B_BH(ptr)->BM); - } - } - clrtoeol(); - } - } -} - -static void -set_menu_BM(char *BM) -{ - if (!HasUserPerm(PERM_NOCITIZEN) && (HasUserPerm(PERM_ALLBOARD) || is_BM(BM))) { - currmode |= MODE_GROUPOP; - cuser.userlevel |= PERM_SYSSUBOP; - } -} - -static void replace_link_by_target(boardstat_t *board) -{ - assert(0<=board->bid-1 && board->bid-1<MAX_BOARD); - board->bid = BRD_LINK_TARGET(getbcache(board->bid)); - board->myattr &= ~NBRD_SYMBOLIC; -} -static int -paste_taged_brds(int gid) -{ - fav_t *fav; - int bid, tmp; - - if (gid == 0 || ! (HasUserPerm(PERM_SYSOP) || GROUPOP()) || - getans("¶K¤W¼Ð°Oªº¬ÝªO?(y/N)")!='y') return 0; - fav = get_fav_root(); - for (tmp = 0; tmp < fav->DataTail; tmp++) { - boardheader_t *bh; - bid = fav_getid(&fav->favh[tmp]); - assert(0<=bid-1 && bid-1<MAX_BOARD); - bh = getbcache(bid); - if( !is_set_attr(&fav->favh[tmp], FAVH_ADM_TAG)) - continue; - set_attr(&fav->favh[tmp], FAVH_ADM_TAG, FALSE); - if (bh->gid != gid) { - bh->gid = gid; - assert(0<=bid-1 && bid-1<MAX_BOARD); - substitute_record(FN_BOARD, bh, - sizeof(boardheader_t), bid); - reset_board(bid); - log_usies("SetBoardGID", bh->brdname); - } - } - sort_bcache(); - return 1; -} - -static void -choose_board(int newflag) -{ - static int num = 0; - boardstat_t *ptr; - int head = -1, ch = 0, currmodetmp, tmp, tmp1, bidtmp; - char keyword[13] = "", buf[PATHLEN]; - - setutmpmode(newflag ? READNEW : READBRD); - if( get_fav_root() == NULL ) - fav_load(); - ++choose_board_depth; - brdnum = 0; - if (!cuser.userlevel) /* guest yank all boards */ - LIST_BRD(); - - do { - if (brdnum <= 0) { - load_boards(keyword); - if (brdnum <= 0) { - if (keyword[0] != 0) { - vmsg("¨S¦³¥ô¦ó¬ÝªO¼ÐÃD¦³¦¹ÃöÁä¦r"); - keyword[0] = 0; - brdnum = -1; - continue; - } - if (IS_LISTING_BRD()) { - if (HasUserPerm(PERM_SYSOP) || GROUPOP()) { - if (paste_taged_brds(class_bid) || - m_newbrd(class_bid, 0) == -1) - break; - brdnum = -1; - continue; - } else - break; - } - } - head = -1; - } - - /* reset the cursor when out of range */ - if (num < 0) - num = 0; - else if (num >= brdnum) - num = brdnum - 1; - - if (head < 0) { - if (newflag) { - tmp = num; - assert(brdnum<=nbrdsize); - while (num < brdnum) { - ptr = &nbrd[num]; - if (ptr->myattr & NBRD_UNREAD) - break; - num++; - } - if (num >= brdnum) - num = tmp; - } - head = (num / p_lines) * p_lines; - show_brdlist(head, 1, newflag); - } else if (num < head || num >= head + p_lines) { - head = (num / p_lines) * p_lines; - show_brdlist(head, 0, newflag); - } - if (IN_CLASSROOT()) - ch = cursor_key(7 + num - head, 10); - else - ch = cursor_key(3 + num - head, 0); - - switch (ch) { - - /////////////////////////////////////////////////////// - // General Hotkeys - /////////////////////////////////////////////////////// - - case 'h': - show_helpfile(fn_boardlisthelp); - show_brdlist(head, 1, newflag); - break; - case Ctrl('W'): - whereami(); - head = -1; - break; - - case 'c': - show_brdlist(head, 1, newflag ^= 1); - break; - case Ctrl('I'): - t_idle(); - show_brdlist(head, 1, newflag); - break; - - case 'e': - case KEY_LEFT: - case EOF: - ch = 'q'; - case 'q': - if (keyword[0]) { - keyword[0] = 0; - brdnum = -1; - ch = ' '; - } - break; - case KEY_PGUP: - case 'P': - case 'b': - case Ctrl('B'): - if (num) { - num -= p_lines; - break; - } - case KEY_END: - case '$': - num = brdnum - 1; - break; - case ' ': - case KEY_PGDN: - case 'N': - case Ctrl('F'): - if (num == brdnum - 1) - num = 0; - else - num += p_lines; - break; - case KEY_UP: - case 'p': - case 'k': - if (num-- <= 0) - num = brdnum - 1; - break; - case '*': - if (IS_LISTING_FAV()) { - int i = 0; - assert(brdnum<=nbrdsize); - for (i = 0; i < brdnum; i++) - { - ptr = &nbrd[i]; - if (IS_LISTING_FAV()){ - assert(nbrdsize>0); - if(get_fav_type(&nbrd[0]) != 0) - fav_tag(ptr->bid, get_fav_type(ptr), 2); - } - ptr->myattr ^= NBRD_TAG; - } - head = 9999; - } - break; - case 't': - assert(0<=num && num<nbrdsize); - ptr = &nbrd[num]; - if (IS_LISTING_FAV()){ - assert(nbrdsize>0); - if(get_fav_type(&nbrd[0]) != 0) - fav_tag(ptr->bid, get_fav_type(ptr), EXCH); - } - else if (HasUserPerm(PERM_SYSOP) || - HasUserPerm(PERM_SYSSUPERSUBOP) || - HasUserPerm(PERM_SYSSUBOP) || - HasUserPerm(PERM_BOARD)) { - /* ¯¸ªøºÞ²z¥Îªº tag */ - if (ptr->myattr & NBRD_TAG) - set_attr(getadmtag(ptr->bid), FAVH_ADM_TAG, FALSE); - else - fav_add_admtag(ptr->bid); - } - ptr->myattr ^= NBRD_TAG; - head = 9999; - case KEY_DOWN: - case 'n': - case 'j': - if (++num < brdnum) - break; - case '0': - case KEY_HOME: - num = 0; - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if ((tmp = search_num(ch, brdnum)) >= 0) - num = tmp; - brdlist_foot(); - break; - - case '/': - getdata_buf(b_lines - 1, 0, "½Ð¿é¤J¬ÝªO¤¤¤åÃöÁä¦r:", - keyword, sizeof(keyword), DOECHO); - brdnum = -1; - break; - case 'S': - if(IS_LISTING_FAV()){ - move(b_lines - 2, 0); clrtobot(); - outs("«·s±Æ§Ç¬ÝªO " - ANSI_COLOR(1;33) "(ª`·N, ³oӰʧ@·|Âмgì¨Ó³]©w)" ANSI_RESET " \n"); - tmp = getans("±Æ§Ç¤è¦¡ (1)«ö·ÓªO¦W±Æ§Ç (2)«ö·ÓÃþ§O±Æ§Ç ==> [0]¨ú®ø "); - if( tmp == '1' ) - fav_sort_by_name(); - else if( tmp == '2' ) - fav_sort_by_class(); - } - else - cuser.uflag ^= BRDSORT_FLAG; - brdnum = -1; - break; - - - case 'v': - case 'V': - assert(0<=num && num<nbrdsize); - ptr = &nbrd[num]; - if(nbrd[num].bid < 0 || !HasBoardPerm(B_BH(ptr))) - break; - if (ch == 'v') { - ptr->myattr &= ~NBRD_UNREAD; - brc_toggle_all_read(ptr->bid, 1); - } else { - brc_toggle_all_read(ptr->bid, 0); - ptr->myattr |= NBRD_UNREAD; - } - show_brdlist(head, 0, newflag); - break; - case 's': - if ((tmp = search_board()) != -1) { - head = -1; - num = tmp; - break; - } - // TODO try global search? - // TODO entering boards is now too complex... - // please refine the code. - // - // if (Select() != NEWDIRECT) { - // } - - // update screen - head = -1; - num = tmp; - break; - - case KEY_RIGHT: - case '\n': - case '\r': - case 'r': - { - if (IS_LISTING_FAV()) { - assert(nbrdsize>0); - if (get_fav_type(&nbrd[0]) == 0) - break; - assert(0<=num && num<nbrdsize); - ptr = &nbrd[num]; - if (ptr->myattr & NBRD_LINE) - break; - if (ptr->myattr & NBRD_FOLDER){ - int t = num; - num = 0; - fav_folder_in(ptr->bid); - choose_board(0); - fav_folder_out(); - num = t; - LIST_FAV(); // XXX press 'y' in fav makes yank_flag = LIST_BRD - brdnum = -1; - head = 9999; - break; - } - } else { - assert(0<=num && num<nbrdsize); - ptr = &nbrd[num]; - if (ptr->myattr & NBRD_SYMBOLIC) { - replace_link_by_target(ptr); - } - } - - assert(0<=ptr->bid-1 && ptr->bid-1<MAX_BOARD); - if (!(B_BH(ptr)->brdattr & BRD_GROUPBOARD)) { /* «Dsub class */ - if (HasBoardPerm(B_BH(ptr))) { - brc_initial_board(B_BH(ptr)->brdname); - - if (newflag) { - setbdir(buf, currboard); - tmp = unread_position(buf, ptr); - head = tmp - t_lines / 2; - getkeep(buf, head > 1 ? head : 1, tmp + 1); - } - Read(); - check_newpost(ptr); - head = -1; - setutmpmode(newflag ? READNEW : READBRD); - } - } else { /* sub class */ - move(12, 1); - bidtmp = class_bid; - currmodetmp = currmode; - tmp1 = num; - num = 0; - if (!(B_BH(ptr)->brdattr & BRD_TOP)) - class_bid = ptr->bid; - else - class_bid = -1; /* ¼öªù¸s²Õ¥Î */ - - if (!GROUPOP()) /* ¦pªGÁÙ¨S¦³¤p²ÕªøÅv */ - set_menu_BM(B_BH(ptr)->BM); - - if (now < B_BH(ptr)->bupdate) { - int mr = 0; - - setbfile(buf, B_BH(ptr)->brdname, fn_notes); - mr = more(buf, NA); - if (mr != -1 && mr != READ_NEXT) - pressanykey(); - } - tmp = currutmp->brc_id; - setutmpbid(ptr->bid); - free(nbrd); - nbrd = NULL; - nbrdsize = 0; - if (IS_LISTING_FAV()) { - LIST_BRD(); - choose_board(0); - LIST_FAV(); - } - else - choose_board(0); - currmode = currmodetmp; /* Â÷¶}ªOªO«á´N§âÅv®³±¼³á */ - num = tmp1; - class_bid = bidtmp; - setutmpbid(tmp); - brdnum = -1; - } - } - break; - /////////////////////////////////////////////////////// - // MyFav Functionality (Require PERM_BASIC) - /////////////////////////////////////////////////////// - case 'y': - if (HasFavEditPerm() && !(IN_CLASS())) { - if (get_current_fav() != NULL || !IS_LISTING_FAV()){ - yank_flag ^= 1; /* FAV <=> BRD */ - } - brdnum = -1; - } - break; - case Ctrl('D'): - if (HasFavEditPerm()) { - if (getans("§R°£©Ò¦³¼Ð°O[N]?") == 'y'){ - fav_remove_all_tagged_item(); - brdnum = -1; - } - } - break; - case Ctrl('A'): - if (HasFavEditPerm()) { - fav_add_all_tagged_item(); - brdnum = -1; - } - break; - case Ctrl('T'): - if (HasFavEditPerm()) { - fav_remove_all_tag(); - brdnum = -1; - } - break; - case Ctrl('P'): - if (paste_taged_brds(class_bid)) - brdnum = -1; - break; - - case 'L': - if ((HasUserPerm(PERM_SYSOP) || - (HasUserPerm(PERM_SYSSUPERSUBOP) && GROUPOP())) && IN_CLASS()) { - // TODO XXX why need symlink here? Can we remove it? - if (make_symbolic_link_interactively(class_bid) < 0) - break; - brdnum = -1; - head = 9999; - } - else if (HasFavEditPerm() && IS_LISTING_FAV()) { - if (fav_add_line() == NULL) { - vmsg("·s¼W¥¢±Ñ¡A¤À¹j½u/Á`³Ì·R ¼Æ¶q¹F³Ì¤jÈ¡C"); - break; - } - /* done move if it's the first item. */ - assert(nbrdsize>0); - if (get_fav_type(&nbrd[0]) != 0) - move_in_current_folder(brdnum, num); - brdnum = -1; - head = 9999; - } - break; - - case 'd': // why don't we enable 'd'? - case 'z': - case 'm': - if (HasFavEditPerm()) { - assert(0<=num && num<nbrdsize); - ptr = &nbrd[num]; - if (IS_LISTING_FAV()) { - if (ptr->myattr & NBRD_FAV) { - if (getans("§A½T©w§R°£¶Ü? [N/y]") != 'y') - break; - fav_remove_item(ptr->bid, get_fav_type(ptr)); - ptr->myattr &= ~NBRD_FAV; - } - } - else - { - if (getboard(ptr->bid) != NULL) { - fav_remove_item(ptr->bid, FAVT_BOARD); - ptr->myattr &= ~NBRD_FAV; - } - else if (ch != 'd') // 'd' only deletes something. - { - if (fav_add_board(ptr->bid) == NULL) - vmsg("§Aªº³Ì·R¤Ó¦h¤F°Õ ¯uªá¤ß"); - else - ptr->myattr |= NBRD_FAV; - } - } - brdnum = -1; - head = 9999; - } - break; - case 'M': - if (HasFavEditPerm()){ - if (IN_FAVORITE() && IS_LISTING_FAV()){ - imovefav(num); - brdnum = -1; - head = 9999; - } - } - break; - case 'g': - if (HasFavEditPerm() && IS_LISTING_FAV()) { - fav_type_t *ft; - if (fav_stack_full()){ - vmsg("¥Ø¿ý¤w¹F³Ì¤j¼h¼Æ!!"); - break; - } - if ((ft = fav_add_folder()) == NULL) { - vmsg("·s¼W¥¢±Ñ¡A¥Ø¿ý/Á`³Ì·R ¼Æ¶q¹F³Ì¤jÈ¡C"); - break; - } - fav_set_folder_title(ft, "·sªº¥Ø¿ý"); - /* don't move if it's the first item */ - assert(nbrdsize>0); - if (get_fav_type(&nbrd[0]) != 0) - move_in_current_folder(brdnum, num); - brdnum = -1; - head = 9999; - } - break; - case 'T': - assert(0<=num && num<nbrdsize); - if (HasFavEditPerm() && nbrd[num].myattr & NBRD_FOLDER) { - fav_type_t *ft = getfolder(nbrd[num].bid); - strlcpy(buf, get_item_title(ft), sizeof(buf)); - getdata_buf(b_lines-1, 0, "½Ðקï¦WºÙ: ", buf, BTLEN+1, DOECHO); - fav_set_folder_title(ft, buf); - brdnum = -1; - } - break; - case 'K': - if (HasFavEditPerm()) { - char c, fname[80]; - if (get_current_fav() != get_fav_root()) { - vmsg("½Ð¨ì§Úªº³Ì·R³Ì¤W¼h°õ¦æ¥»¥\\¯à"); - break; - } - - c = getans("½Ð¿ï¾Ü 2)³Æ¥÷§Úªº³Ì·R 3)¨ú¦^³Ì·R³Æ¥÷ [Q]"); - if(!c) - break; - if(getans("½T©w¶Ü [y/N] ") != 'y') - break; - switch(c){ - case '2': - fav_save(); - setuserfile(fname, FAV); - sprintf(buf, "%s.bak", fname); - Copy(fname, buf); - break; - case '3': - setuserfile(fname, FAV); - sprintf(buf, "%s.bak", fname); - if (!dashf(buf)){ - vmsg("§A¨S¦³³Æ¥÷§Aªº³Ì·R³á"); - break; - } - Copy(buf, fname); - fav_free(); - fav_load(); - break; - } - brdnum = -1; - } - break; - - case 'a': - case 'i': - if(IN_FAVORITE() && HasFavEditPerm()){ - char bname[IDLEN + 1]; - int bid; - move(0, 0); - clrtoeol(); - /* use CompleteBoard or CompleteBoardAndGroup ? */ - CompleteBoard(ANSI_COLOR(7) "¡i ¼W¥[§Úªº³Ì·R ¡j" ANSI_RESET "\n" - "½Ð¿é¤J±ý¥[¤Jªº¬ÝªO¦WºÙ(«öªÅ¥ÕÁä¦Û°Ê·j´M)¡G", - bname); - - if (bname[0] && (bid = getbnum(bname)) && - HasBoardPerm(getbcache(bid))) { - fav_type_t * ptr = getboard(bid); - if (ptr != NULL) { // already in fav list - // move curser to item - for (num = 0; num<nbrdsize && bid != nbrd[num].bid; ++num); - assert(bid==nbrd[num].bid); - } else { - ptr = fav_add_board(bid); - - if (ptr == NULL) - vmsg("§Aªº³Ì·R¤Ó¦h¤F°Õ ¯uªá¤ß"); - else { - ptr->attr |= NBRD_FAV; - - if (ch == 'i' && get_data_number(get_current_fav()) > 1) - move_in_current_folder(brdnum, num); - else - num = brdnum; - } - } - } - } - brdnum = -1; - head = 9999; - break; - - case 'w': - /* allowing save BRC/fav once per 10 minutes */ - if (now - last_save_fav_and_brc > 10 * 60) { - fav_save(); - brc_finalize(); - - last_save_fav_and_brc = now; - } - break; - - /////////////////////////////////////////////////////// - // Administrator Only - /////////////////////////////////////////////////////// - - case 'F': - case 'f': - if (HasUserPerm(PERM_SYSOP)) { - getbcache(class_bid)->firstchild[cuser.uflag & BRDSORT_FLAG ? 1 : 0] = 0; - brdnum = -1; - } - break; - case 'D': - if (HasUserPerm(PERM_SYSOP) || - (HasUserPerm(PERM_SYSSUPERSUBOP) && GROUPOP())) { - assert(0<=num && num<nbrdsize); - ptr = &nbrd[num]; - if (ptr->myattr & NBRD_SYMBOLIC) { - if (getans("½T©w§R°£³sµ²¡H[N/y]") == 'y') - delete_symbolic_link(getbcache(ptr->bid), ptr->bid); - } - brdnum = -1; - } - break; - case 'E': - if (HasUserPerm(PERM_SYSOP | PERM_BOARD) || GROUPOP()) { - assert(0<=num && num<nbrdsize); - ptr = &nbrd[num]; - move(1, 1); - clrtobot(); - m_mod_board(B_BH(ptr)->brdname); - brdnum = -1; - } - break; - case 'R': - if (HasUserPerm(PERM_SYSOP) || GROUPOP()) { - m_newbrd(class_bid, 1); - brdnum = -1; - } - break; - case 'B': - if (HasUserPerm(PERM_SYSOP) || GROUPOP()) { - m_newbrd(class_bid, 0); - brdnum = -1; - } - break; - case 'W': - if (IN_SUBCLASS() && - (HasUserPerm(PERM_SYSOP) || GROUPOP())) { - setbpath(buf, getbcache(class_bid)->brdname); - mkdir(buf, 0755); /* Ptt:¶}¸s²Õ¥Ø¿ý */ - b_note_edit_bname(class_bid); - brdnum = -1; - } - break; - - } - } while (ch != 'q'); - free(nbrd); - nbrd = NULL; - nbrdsize = 0; - --choose_board_depth; -} - -int -Class(void) -{ - init_brdbuf(); - class_bid = 1; - LIST_BRD(); - choose_board(0); - return 0; -} - -int -Favorite(void) -{ - init_brdbuf(); - class_bid = 0; - LIST_FAV(); - choose_board(0); - return 0; -} - - -int -New(void) -{ - int mode0 = currutmp->mode; - int stat0 = currstat; - - class_bid = 0; - init_brdbuf(); - choose_board(1); - currutmp->mode = mode0; - currstat = stat0; - return 0; -} diff --git a/mbbsd/brc.c b/mbbsd/brc.c deleted file mode 100644 index 4317dfd1..00000000 --- a/mbbsd/brc.c +++ /dev/null @@ -1,596 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -/** - * Ãö©ó¥»Àɮתº²Ó¸`¡A½Ð¨£ docs/brc.txt¡C - * v3: add last modified time for comment system. double max size. - * original time_t as 'create'. - */ - -// WARNING: Check ../pttbbs.conf, you may have overide these value there -// TODO MAXSIZE may be better smaller to fit into memory page. -#ifndef BRC_MAXNUM -#define BRC_MAXSIZE 49152 /* Effective size of brc rc file, 8192 * 3 * 2 */ -#define BRC_MAXNUM 80 /* Upper bound of brc_num, size of brc_list */ -#endif - -#define BRC_BLOCKSIZE 1024 - -// Note: BRC v3 should already support MAX_BOARD > 65535 and BRC_MAXSIZE > 65535, -// but not widely tested yet. -#if MAX_BOARD > 65535 || BRC_MAXSIZE > 65535 -#error Max number of boards or BRC_MAXSIZE cannot fit in unsigned short, \ -please rewrite brc.c (v2) -#endif - -typedef uint32_t brcbid_t; -typedef uint16_t brcnbrd_t; - -typedef struct { - time4_t create; - time4_t modified; -} brc_rec; - -/* old brc rc file form: - * board_name 15 bytes - * brc_num 1 byte, binary integer - * brc_list brc_num * sizeof(brc_rec) bytes */ - -static char brc_initialized = 0; -static time4_t brc_expire_time; - /* Will be set to the time one year before login. All the files created - * before then will be recognized read. */ - -static int brc_changed = 0; /**< brc_list/brc_num changed */ -/* The below two will be filled by read_brc_buf() and brc_update() */ -static char *brc_buf = NULL; -static int brc_size; -static int brc_alloc; - -// read records for currbid -static int brc_currbid; -static int brc_num; -static brc_rec brc_list[BRC_MAXNUM]; - -static char * const fn_brc2= ".brc2"; -static char * const fn_brc = ".brc3"; - -/** - * find read records of bid in given buffer region - * - * @param[in] begin - * @param[in] endp - * @param bid - * @param[out] num number of records, which could be written for \a bid - * = brc_num if found - * = 0 or dangling size if not found - * - * @return address of record. \a begin <= addr < \a endp. - * 0 if not found - */ -/* Returns the address of the record strictly between begin and endp with - * bid equal to the parameter. Returns 0 if not found. - * brcnbrd_t *num is an output parameter which will filled with brc_num - * if the record is found. If not found the record, *num will be the number - * of dangling bytes. */ -static char * -brc_findrecord_in(char *begin, char *endp, brcbid_t bid, brcnbrd_t *num) -{ - char *tmpp, *ptr = begin; - brcbid_t tbid; - while (ptr + sizeof(brcbid_t) + sizeof(brcnbrd_t) < endp) { - /* for each available records */ - tmpp = ptr; - tbid = *(brcbid_t*)tmpp; - tmpp += sizeof(brcbid_t); - *num = *(brcnbrd_t*)tmpp; - tmpp += sizeof(brcnbrd_t) + *num * sizeof(brc_rec); /* end of record */ - - if ( tmpp > endp ){ - /* dangling, ignore the trailing data */ - *num = (brcnbrd_t)(endp - ptr); /* for brc_insert_record() */ - return 0; - } - if ( tbid == bid ) - return ptr; - ptr = tmpp; - } - - *num = 0; - return 0; -} - -static brc_rec * -brc_find_record(int bid, int *num) -{ - char *p; - brcnbrd_t tnum; - p = brc_findrecord_in(brc_buf, brc_buf + brc_size, bid, &tnum); - *num = tnum; - if (p) - return (brc_rec*)(p + sizeof(brcbid_t) + sizeof(brcnbrd_t)); - *num = 0; - return 0; -} - -static char * -brc_putrecord(char *ptr, char *endp, brcbid_t bid, - brcnbrd_t num, const brc_rec *list) -{ - char * tmp; - if (num > 0 && list[0].create > brc_expire_time && - ptr + sizeof(brcbid_t) + sizeof(brcnbrd_t) < endp) { - if (num > BRC_MAXNUM) - num = BRC_MAXNUM; - - if (num == 0) return ptr; - - *(brcbid_t*)ptr = bid; /* write in bid */ - ptr += sizeof(brcbid_t); - *(brcnbrd_t*)ptr = num; /* write in brc_num */ - ptr += sizeof(brcnbrd_t); - tmp = ptr + num * sizeof(brc_rec); - if (tmp <= endp) - memcpy(ptr, list, num * sizeof(brc_rec)); /* write in brc_list */ - ptr = tmp; - } - return ptr; -} - -static inline int -brc_enlarge_buf(void) -{ - char *buffer; - if (brc_alloc >= BRC_MAXSIZE) - return 0; - -#ifdef CRITICAL_MEMORY -#define THE_MALLOC(X) MALLOC(X) -#define THE_FREE(X) FREE(X) -#else -#define THE_MALLOC(X) alloca(X) -#define THE_FREE(X) (void)(X) - /* alloca get memory from stack and automatically freed when - * function returns. */ -#endif - - buffer = (char*)THE_MALLOC(brc_alloc); - assert(buffer); - - memcpy(buffer, brc_buf, brc_alloc); - free(brc_buf); - brc_alloc += BRC_BLOCKSIZE; - brc_buf = (char*)malloc(brc_alloc); - assert(brc_buf); - memcpy(brc_buf, buffer, brc_alloc - BRC_BLOCKSIZE); - -#ifdef DEBUG - vmsgf("brc enlarged to %d bytes", brc_alloc); -#endif - - THE_FREE(buffer); - return 1; - -#undef THE_MALLOC -#undef THE_FREE -} - -static inline void -brc_get_buf(int size){ - if (!size) - brc_alloc = BRC_BLOCKSIZE; - else - brc_alloc = (size + BRC_BLOCKSIZE - 1) / BRC_BLOCKSIZE * BRC_BLOCKSIZE; - if (brc_alloc > BRC_MAXSIZE) - brc_alloc = BRC_MAXSIZE; - brc_buf = (char*)malloc(brc_alloc); - assert(brc_buf); -} - -static inline void -brc_insert_record(brcbid_t bid, brcnbrd_t num, const brc_rec* list) -{ - char *ptr; - int new_size, end_size; - brcnbrd_t tnum; - - ptr = brc_findrecord_in(brc_buf, brc_buf + brc_size, bid, &tnum); - - while (num > 0 && list[num - 1].create < brc_expire_time) - num--; /* don't write the times before brc_expire_time */ - - if (!ptr) { - brc_size -= (int)tnum; - - /* put on the beginning */ - if (num){ - new_size = sizeof(brcbid_t) + sizeof(brcnbrd_t) - + num * sizeof(brc_rec); - brc_size += new_size; - if (brc_size > brc_alloc && !brc_enlarge_buf()) - brc_size = BRC_MAXSIZE; - if (brc_size > new_size) - memmove(brc_buf + new_size, brc_buf, brc_size - new_size); - brc_putrecord(brc_buf, brc_buf + new_size, bid, num, list); - } - } else { - /* ptr points to the old current brc list. - * tmpp is the end of it (exclusive). */ - int len = sizeof(brcbid_t) + sizeof(brcnbrd_t) + tnum * sizeof(brc_rec); - char *tmpp = ptr + len; - end_size = brc_buf + brc_size - tmpp; - if (num) { - int sindex = ptr - brc_buf; - new_size = (sizeof(brcbid_t) + sizeof(brcnbrd_t) - + num * sizeof(brc_rec)); - brc_size += new_size - len; - if (brc_size > brc_alloc) { - if (brc_enlarge_buf()) { - ptr = brc_buf + sindex; - tmpp = ptr + len; - } else { - end_size -= brc_size - BRC_MAXSIZE; - brc_size = BRC_MAXSIZE; - } - } - if (end_size > 0 && ptr + new_size != tmpp) - memmove(ptr + new_size, tmpp, end_size); - brc_putrecord(ptr, brc_buf + brc_alloc, bid, num, list); - } else { /* deleting record */ - memmove(ptr, tmpp, end_size); - brc_size -= len; - } - } - - brc_changed = 0; -} - -/** - * write \a brc_num and \a brc_list back to \a brc_buf. - */ -void -brc_update(){ - if (brc_currbid && brc_changed && cuser.userlevel && brc_num > 0) { - brc_initialize(); - brc_insert_record(brc_currbid, brc_num, brc_list); - } -} - -void -read_brc2(void) -{ - char brcfile[STRLEN]; - int fd; - size_t sz2 = 0, sz3 = 0; - char *cvt = NULL, *cvthead = NULL; - - // brc v2 is using 16 bit for brcbid_t and brcnbrd_t. - uint16_t bid2, num2; - - brcbid_t bid; - brcnbrd_t num; - time4_t create; - brc_rec rec; - - setuserfile(brcfile, fn_brc2); - - if ((fd = open(brcfile, O_RDONLY)) == -1) - return; - - sz2 = dashs(brcfile); - sz3 = sz2 * 2; // max double size - - cvthead = cvt = malloc (sz3); - memset(cvthead, 0, sz3); - // now calculate real sz3 - - while (read(fd, &bid2, sizeof(bid2)) > 0) - { - if (read(fd, &num2, sizeof(num2)) < 1) - break; - - bid = bid2; - num = num2; - - // some brc v2 contains bad structure. - // check pointer here. - if (cvt + sizeof(brcbid_t) + sizeof(brcnbrd_t) - cvthead >= sz3) - break; - - *(brcbid_t*) cvt = bid; cvt += sizeof(brcbid_t); - *(brcnbrd_t*)cvt = num; cvt += sizeof(brcnbrd_t); - - // some brc v2 contains bad structure. - // check pointer here. - for (; num > 0 && (cvt + sizeof(brc_rec) - cvthead) <= sz3 ; num--) - { - if (read(fd, &create, sizeof(create)) < 1) - break; - - rec.create = create; - rec.modified = create; - - *(brc_rec*)cvt = rec; cvt += sizeof(brc_rec); - } - } - close(fd); - - // now cvthead is ready for v3. - sz3 = cvt - cvthead; - brc_get_buf(sz3); - // new size maybe smaller, check brc_alloc instead - if (sz3 > brc_alloc) - sz3 = brc_alloc; - brc_size = sz3; - memcpy(brc_buf, cvthead, sz3); - - free(cvthead); -} - -inline static void -read_brc_buf(void) -{ - char brcfile[STRLEN]; - int fd; - struct stat brcstat; - - if (brc_buf != NULL) - return; - - brc_size = 0; - setuserfile(brcfile, fn_brc); - - if ((fd = open(brcfile, O_RDONLY)) == -1) - { - read_brc2(); - return; - } - - fstat(fd, &brcstat); - brc_get_buf(brcstat.st_size); - brc_size = read(fd, brc_buf, brc_alloc); - close(fd); -} - -/* release allocated memory - * - * Do not destory brc_currbid, brc_num, brc_list. - */ -void -brc_release() -{ - if (brc_buf) { - free(brc_buf); - brc_buf = NULL; - } - brc_changed = 0; - brc_size = brc_alloc = 0; -} - -void -brc_finalize(){ - char brcfile[STRLEN]; - char tmpfile[STRLEN]; - - if(!brc_initialized) - return; - - brc_update(); - setuserfile(brcfile, fn_brc); - snprintf(tmpfile, sizeof(tmpfile), "%s.tmp.%x", brcfile, getpid()); - if (brc_buf != NULL) { - int fd = open(tmpfile, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd != -1) { - int ok=0; - if(write(fd, brc_buf, brc_size)==brc_size) - ok=1; - close(fd); - if(ok) - Rename(tmpfile, brcfile); - else - unlink(tmpfile); - } - } - - brc_release(); - brc_initialized = 0; -} - -int -brc_initialize(){ - if (brc_initialized) - return 1; - brc_initialized = 1; - brc_expire_time = login_start_time - 365 * 86400; - read_brc_buf(); - return 0; -} - -/** - * get the read records for bid - * - * @param bid - * @param[out] num number of record for \a bid. 1 <= \a num <= \a BRC_MAXNUM - * \a num = 1 if no records. - * @param[out] list the list of records, length \a num - * - * @return number of read record, 0 if no records - */ -static int -brc_read_record(int bid, int *num, brc_rec *list){ - char *ptr; - brcnbrd_t tnum; - ptr = brc_findrecord_in(brc_buf, brc_buf + brc_size, bid, &tnum); - *num = tnum; - if ( ptr ){ - assert(0 <= *num && *num <= BRC_MAXNUM); - memcpy(list, ptr + sizeof(brcbid_t) + sizeof(brcnbrd_t), - *num * sizeof(brc_rec)); - return *num; - } - list[0].create = *num = 1; - return 0; -} - -/** - * @return number of records in \a boardname - */ -int -brc_initial_board(const char *boardname) -{ - brc_initialize(); - - if (strcmp(currboard, boardname) == 0) { - assert(currbid == brc_currbid); - return brc_num; - } - - brc_update(); /* write back first */ - currbid = getbnum(boardname); - if( currbid == 0 ) - currbid = getbnum(DEFAULT_BOARD); - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - brc_currbid = currbid; - currboard = bcache[currbid - 1].brdname; - currbrdattr = bcache[currbid - 1].brdattr; - - return brc_read_record(brc_currbid, &brc_num, brc_list); -} - -static void -brc_trunc(int bid, time4_t ftime){ - brc_rec r; - - r.create = ftime; - r.modified = ftime; - brc_insert_record(bid, 1, &r); - if ( bid == brc_currbid ){ - brc_num = 1; - brc_list[0] = r; - brc_changed = 0; - } -} - -void -brc_toggle_all_read(int bid, int is_all_read) -{ - brc_initialize(); - if (is_all_read) - brc_trunc(bid, now); - else - brc_trunc(bid, 1); -} - -void -brc_addlist(const char *fname, time4_t modified) -{ - int n, i; - brc_rec frec; - - assert(currbid == brc_currbid); - if (!cuser.userlevel) - return; - brc_initialize(); - - frec.create = atoi(&fname[2]); - frec.modified = modified; - - if (frec.create <= brc_expire_time /* too old, don't do any thing */ - /* || fname[0] != 'M' || fname[1] != '.' */ ) { - return; - } - if (brc_num <= 0) { /* uninitialized */ - brc_list[0] = frec; - brc_num = 1; - brc_changed = 1; - return; - } - if ((brc_num == 1) && (frec.create < brc_list[0].create)) /* most when after 'v' */ - return; - for (n = 0; n < brc_num; n++) { /* using linear search */ - if (frec.create == brc_list[n].create) { - // check if we got bad value. - if (modified == (time4_t)-1) - return; - - if (brc_list[n].modified == (time4_t)-1) - brc_list[n].modified = 0; - - // special case here: - // in order to support special system like 'always bottom', - // they may share same create time and different time. - if (brc_list[n].modified < modified) - { - brc_list[n].modified = modified; - brc_changed = 1; - } - return; - } else if (frec.create > brc_list[n].create) { - if (brc_num < BRC_MAXNUM) - brc_num++; - /* insert frec into brc_list */ - for (i = brc_num - 1; --i >= n; brc_list[i + 1] = brc_list[i]); - brc_list[n] = frec; - brc_changed = 1; - return; - } - } -} - -// return: -// 0 - read -// 1 - unread (by create) -// 2 - unread (by modified) -int -brc_unread_time(int bid, time4_t ftime, time4_t modified) -{ - int i; - int bnum; - const brc_rec *blist; - - brc_initialize(); - if (ftime <= brc_expire_time) /* too old */ - return 0; - - if (brc_currbid && bid == brc_currbid) { - blist = brc_list; - bnum = brc_num; - } else { - blist = brc_find_record(bid, &bnum); - } - - if (bnum <= 0) - return 1; - - for (i = 0; i < bnum; i++) { /* using linear search */ - if (ftime > blist[i].create) - return 1; - else if (ftime == blist[i].create) - { - time4_t brcm = blist[i].modified; - if (modified == 0 || brcm == 0) - return 0; - - // bad case... seems like that someone is making -1. - if (modified == (time4_t)-1 || brcm == (time4_t)-1) - return 0; - - // one case is, some special file headers (ex, - // always bottom) may cause issue. They share create - // time (filename) and apply different modify time. - // so let's back to 'greater'. - return modified > brcm ? 2 : 0; - } - } - return 0; -} - -int -brc_unread(int bid, const char *fname, time4_t modified) -{ - int ftime; - - ftime = atoi(&fname[2]); /* this will get the time of the file created */ - - return brc_unread_time(bid, ftime, modified); -} diff --git a/mbbsd/cache.c b/mbbsd/cache.c deleted file mode 100644 index 5a30c24f..00000000 --- a/mbbsd/cache.c +++ /dev/null @@ -1,1215 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#ifdef _BBS_UTIL_C_ -# define log_usies(a, b) ; -# define abort_bbs(a) exit(1) -#endif -/* - * the reason for "safe_sleep" is that we may call sleep during SIGALRM - * handler routine, while SIGALRM is blocked. if we use the original sleep, - * we'll never wake up. - */ -unsigned int -safe_sleep(unsigned int seconds) -{ - /* jochang sleep¦³°ÝÃD®É¥Î */ - sigset_t set, oldset; - - sigemptyset(&set); - sigprocmask(SIG_BLOCK, &set, &oldset); - if (sigismember(&oldset, SIGALRM)) { - unsigned int retv; - log_usies("SAFE_SLEEP ", "avoid hang"); - sigemptyset(&set); - sigaddset(&set, SIGALRM); - sigprocmask(SIG_UNBLOCK, &set, NULL); - retv = sleep(seconds); - sigprocmask(SIG_BLOCK, &set, NULL); - return retv; - } - return sleep(seconds); -} - -/* - * section - SHM - */ -static void -attach_err(int shmkey, const char *name) -{ - fprintf(stderr, "[%s error] key = %x\n", name, shmkey); - fprintf(stderr, "errno = %d: %s\n", errno, strerror(errno)); - exit(1); -} - -void * -attach_shm(int shmkey, int shmsize) -{ - void *shmptr = (void *)NULL; - int shmid; - - shmid = shmget(shmkey, shmsize, -#ifdef USE_HUGETLB - SHM_HUGETLB | -#endif - 0); - if (shmid < 0) { - // SHM should be created by uhash_loader, NOT mbbsd or other utils - attach_err(shmkey, "shmget"); - } else { - shmptr = (void *)shmat(shmid, NULL, 0); - if (shmptr == (void *)-1) - attach_err(shmkey, "shmat"); - } - - return shmptr; -} - -void -attach_SHM(void) -{ - SHM = attach_shm(SHM_KEY, SHMSIZE); - if(SHM->version != SHM_VERSION) { - fprintf(stderr, "Error: SHM->version(%d) != SHM_VERSION(%d)\n", SHM->version, SHM_VERSION); - fprintf(stderr, "Please use the source code version corresponding to SHM,\n" - "or use ipcrm(1) command to clean share memory.\n"); - exit(1); - } - if (!SHM->loaded) /* (uhash) assume fresh shared memory is - * zeroed */ - exit(1); - if (SHM->Btouchtime == 0) - SHM->Btouchtime = 1; - bcache = SHM->bcache; - numboards = SHM->Bnumber; - - if (SHM->Ptouchtime == 0) - SHM->Ptouchtime = 1; - - if (SHM->Ftouchtime == 0) - SHM->Ftouchtime = 1; -} - -/* ----------------------------------------------------- */ -/* semaphore : for critical section */ -/* ----------------------------------------------------- */ -#define SEM_FLG 0600 /* semaphore mode */ - -#ifndef __FreeBSD__ -/* according to X/OPEN, we have to define it ourselves */ -union semun { - int val; /* value for SETVAL */ - struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ - unsigned short int *array; /* array for GETALL, SETALL */ - struct seminfo *__buf; /* buffer for IPC_INFO */ -}; -#endif - -void -sem_init(int semkey, int *semid) -{ - union semun s; - - s.val = 1; - *semid = semget(semkey, 1, 0); - if (*semid == -1) { - *semid = semget(semkey, 1, IPC_CREAT | SEM_FLG); - if (*semid == -1) - attach_err(semkey, "semget"); - semctl(*semid, 0, SETVAL, s); - } -} - -void -sem_lock(int op, int semid) -{ - struct sembuf sops; - - sops.sem_num = 0; - sops.sem_flg = SEM_UNDO; - sops.sem_op = op; - if (semop(semid, &sops, 1)) { - perror("semop"); - exit(1); - } -} - -/* - * section - user cache(including uhash) - */ -/* uhash ****************************************** */ -/* - * the design is this: we use another stand-alone program to create and load - * data into the hash. (that program could be run in rc-scripts or something - * like that) after loading completes, the stand-alone program sets loaded to - * 1 and exits. - * - * the bbs exits if it can't attach to the shared memory or the hash is not - * loaded yet. - */ - -void -add_to_uhash(int n, const char *id) -{ - int *p, h = StringHash(id)%(1<<HASH_BITS); - int times; - strlcpy(SHM->userid[n], id, sizeof(SHM->userid[n])); - - p = &(SHM->hash_head[h]); - - for (times = 0; times < MAX_USERS && *p != -1; ++times) - p = &(SHM->next_in_hash[*p]); - - if (times == MAX_USERS) - abort_bbs(0); - - SHM->next_in_hash[*p = n] = -1; -} - -void -remove_from_uhash(int n) -{ -/* - * note: after remove_from_uhash(), you should add_to_uhash() (likely with a - * different name) - */ - int h = StringHash(SHM->userid[n])%(1<<HASH_BITS); - int *p = &(SHM->hash_head[h]); - int times; - - for (times = 0; times < MAX_USERS && (*p != -1 && *p != n); ++times) - p = &(SHM->next_in_hash[*p]); - - if (times == MAX_USERS) - abort_bbs(0); - - if (*p == n) - *p = SHM->next_in_hash[n]; -} - -#if (1<<HASH_BITS)*10 < MAX_USERS -#warning "Suggest to use bigger HASH_BITS for better searchuser() performance," -#warning "searchuser() average chaining MAX_USERS/(1<<HASH_BITS) times." -#endif -int -dosearchuser(const char *userid, char *rightid) -{ - int h, p, times; - STATINC(STAT_SEARCHUSER); - h = StringHash(userid)%(1<<HASH_BITS); - p = SHM->hash_head[h]; - - for (times = 0; times < MAX_USERS && p != -1 && p < MAX_USERS ; ++times) { - if (strcasecmp(SHM->userid[p], userid) == 0) { - if(userid[0] && rightid) strcpy(rightid, SHM->userid[p]); - return p + 1; - } - p = SHM->next_in_hash[p]; - } - - return 0; -} - -int -searchuser(const char *userid, char *rightid) -{ - if(userid[0]=='\0') - return 0; - return dosearchuser(userid, rightid); -} - -int -getuser(const char *userid, userec_t *xuser) -{ - int uid; - - if ((uid = searchuser(userid, NULL))) { - passwd_query(uid, xuser); - xuser->money = moneyof(uid); - } - return uid; -} - -char * -getuserid(int num) -{ - if (--num >= 0 && num < MAX_USERS) - return ((char *)SHM->userid[num]); - return NULL; -} - -void -setuserid(int num, const char *userid) -{ - if (num > 0 && num <= MAX_USERS) { -/* Ptt: it may cause problems - if (num > SHM->number) - SHM->number = num; - else -*/ - remove_from_uhash(num - 1); - add_to_uhash(num - 1, userid); - } -} - -#ifndef _BBS_UTIL_C_ -char * -u_namearray(char buf[][IDLEN + 1], int *pnum, char *tag) -{ - register char *ptr, tmp; - register int n, total; - char tagbuf[STRLEN]; - int ch, ch2, num; - - if (*tag == '\0') { - *pnum = SHM->number; - return SHM->userid[0]; - } - for (n = 0; tag[n]; n++) - tagbuf[n] = chartoupper(tag[n]); - tagbuf[n] = '\0'; - ch = tagbuf[0]; - ch2 = ch - 'A' + 'a'; - total = SHM->number; - for (n = num = 0; n < total; n++) { - ptr = SHM->userid[n]; - tmp = *ptr; - if (tmp == ch || tmp == ch2) { - if (chkstr(tag, tagbuf, ptr)) - strcpy(buf[num++], ptr); - } - } - *pnum = num; - return buf[0]; -} -#endif - -void -getnewutmpent(const userinfo_t * up) -{ -/* Ptt:³o¸Ì¥[¤W hash Æ[©À§äªÅªº utmp */ - register int i; - register userinfo_t *uentp; - unsigned int p = StringHash(up->userid) % USHM_SIZE; - for (i = 0; i < USHM_SIZE; i++, p++) { - if (p == USHM_SIZE) - p = 0; - uentp = &(SHM->uinfo[p]); - if (!(uentp->pid)) { - memcpy(uentp, up, sizeof(userinfo_t)); - currutmp = uentp; - return; - } - } - exit(1); -} - -int -apply_ulist(int (*fptr) (const userinfo_t *)) -{ - register userinfo_t *uentp; - register int i, state; - - for (i = 0; i < USHM_SIZE; i++) { - uentp = &(SHM->uinfo[i]); - if (uentp->pid && (PERM_HIDE(currutmp) || !PERM_HIDE(uentp))) - if ((state = (*fptr) (uentp))) - return state; - } - return 0; -} - -userinfo_t * -search_ulist_pid(int pid) -{ - register int i = 0, j, start = 0, end = SHM->UTMPnumber - 1; - int *ulist; - register userinfo_t *u; - if (end == -1) - return NULL; - ulist = SHM->sorted[SHM->currsorted][8]; - for (i = ((start + end) / 2);; i = (start + end) / 2) { - u = &SHM->uinfo[ulist[i]]; - j = pid - u->pid; - if (!j) { - return u; - } - if (end == start) { - break; - } else if (i == start) { - i = end; - start = end; - } else if (j > 0) - start = i; - else - end = i; - } - return 0; -} - -userinfo_t * -search_ulistn(int uid, int unum) -{ - register int i = 0, j, start = 0, end = SHM->UTMPnumber - 1; - int *ulist; - register userinfo_t *u; - if (end == -1) - return NULL; - ulist = SHM->sorted[SHM->currsorted][7]; - for (i = ((start + end) / 2);; i = (start + end) / 2) { - u = &SHM->uinfo[ulist[i]]; - j = uid - u->uid; - if (j == 0) { - for (; i > 0 && uid == SHM->uinfo[ulist[i - 1]].uid; --i) - ;/* «ü¨ì²Ä¤@µ§ */ - // piaip Tue Jan 8 09:28:03 CST 2008 - // many people bugged about that their utmp have invalid - // entry on record. - // we found them caused by crash process (DEBUGSLEEPING) which - // may occupy utmp entries even after process was killed. - // because the memory is invalid, it is not safe for those process - // to wipe their utmp entry. it should be done by some external - // daemon. - // however, let's make a little workaround here... - for (; unum > 0 && i >= 0 && ulist[i] >= 0 && - SHM->uinfo[ulist[i]].uid == uid; unum--, i++) - { - if (SHM->uinfo[ulist[i]].mode == DEBUGSLEEPING) - unum ++; - } - if (unum == 0 && i > 0 && ulist[i-1] >= 0 && - SHM->uinfo[ulist[i-1]].uid == uid) - return &SHM->uinfo[ulist[i-1]]; - /* - if ( i + unum - 1 >= 0 && - (ulist[i + unum - 1] >= 0 && - uid == SHM->uinfo[ulist[i + unum - 1]].uid ) ) - return &SHM->uinfo[ulist[i + unum - 1]]; - */ - break; /* ¶W¹L½d³ò */ - } - if (end == start) { - break; - } else if (i == start) { - i = end; - start = end; - } else if (j > 0) - start = i; - else - end = i; - } - return 0; -} - -userinfo_t * -search_ulist_userid(const char *userid) -{ - register int i = 0, j, start = 0, end = SHM->UTMPnumber - 1; - int *ulist; - register userinfo_t * u; - if (end == -1) - return NULL; - ulist = SHM->sorted[SHM->currsorted][0]; - for (i = ((start + end) / 2);; i = (start + end) / 2) { - u = &SHM->uinfo[ulist[i]]; - j = strcasecmp(userid, u->userid); - if (!j) { - return u; - } - if (end == start) { - break; - } else if (i == start) { - i = end; - start = end; - } else if (j > 0) - start = i; - else - end = i; - } - return 0; -} - -#ifndef _BBS_UTIL_C_ -int -count_logins(int uid, int show) -{ - register int i = 0, j, start = 0, end = SHM->UTMPnumber - 1, count; - int *ulist; - userinfo_t *u; - if (end == -1) - return 0; - ulist = SHM->sorted[SHM->currsorted][7]; - for (i = ((start + end) / 2);; i = (start + end) / 2) { - u = &SHM->uinfo[ulist[i]]; - j = uid - u->uid; - if (!j) { - for (; i > 0 && uid == SHM->uinfo[ulist[i - 1]].uid; i--); - /* «ü¨ì²Ä¤@µ§ */ - for (count = 0; (ulist[i + count] && - (u = &SHM->uinfo[ulist[i + count]]) && - uid == u->uid); count++) { - if (show) - prints("(%d) ¥Ø«eª¬ºA¬°: %-17.16s(¨Ó¦Û %s)\n", - count + 1, modestring(u, 0), - u->from); - } - return count; - } - if (end == start) { - break; - } else if (i == start) { - i = end; - start = end; - } else if (j > 0) - start = i; - else - end = i; - } - return 0; -} - -void -purge_utmp(userinfo_t * uentp) -{ - logout_friend_online(uentp); - memset(uentp, 0, sizeof(userinfo_t)); - SHM->UTMPneedsort = 1; -} -#endif - -/* - * section - money cache - */ -int -setumoney(int uid, int money) -{ - SHM->money[uid - 1] = money; - passwd_update_money(uid); - return SHM->money[uid - 1]; -} - -int -deumoney(int uid, int money) -{ - if (uid <= 0 || uid > MAX_USERS){ -#if defined(_BBS_UTIL_C_) - printf("internal error: deumoney(%d, %d)\n", uid, money); -#else - vmsg("internal error"); -#endif - return -1; - } - - if (money < 0 && moneyof(uid) < -money) - return setumoney(uid, 0); - else - return setumoney(uid, SHM->money[uid - 1] + money); -} - -/* - * section - utmp - */ -#if !defined(_BBS_UTIL_C_) /* _BBS_UTIL_C_ ¤£·|¦³ utmp */ -void -setutmpmode(unsigned int mode) -{ - if (currstat != mode) - currutmp->mode = currstat = mode; - /* °lÂÜ¨Ï¥ÎªÌ */ - if (HasUserPerm(PERM_LOGUSER)) { - log_user("setutmpmode to %s(%d)\n", modestring(currutmp, 0), mode); - } -} - -unsigned int -getutmpmode(void) -{ - if (currutmp) - return currutmp->mode; - return currstat; -} -#endif - -/* - * section - board cache - */ -void touchbtotal(int bid) { - assert(0<=bid-1 && bid-1<MAX_BOARD); - SHM->total[bid - 1] = 0; - SHM->lastposttime[bid - 1] = 0; -} - - -/** - * qsort comparison function - ·ÓªO¦W±Æ§Ç - */ -static int -cmpboardname(const void * i, const void * j) -{ - return strcasecmp(bcache[*(int*)i].brdname, bcache[*(int*)j].brdname); -} - -/** - * qsort comparison function - ¥ý·Ó¸s²Õ±Æ§Ç¡B¦P¤@Ó¸s²Õ¤º¨ÌªO¦W±Æ - */ -static int -cmpboardclass(const void * i, const void * j) -{ - boardheader_t *brd1 = &bcache[*(int*)i], *brd2 = &bcache[*(int*)j]; - int cmp; - - cmp=strncmp(brd1->title, brd2->title, 4); - if(cmp!=0) return cmp; - return strcasecmp(brd1->brdname, brd2->brdname); -} - - -void -sort_bcache(void) -{ - int i; - /* critical section ºÉ¶q¤£n©I¥s */ - /* ¥u¦³·s¼W ©Î²¾°£¬ÝªO »Ýn©I¥s¨ì */ - if(SHM->Bbusystate) { - sleep(1); - return; - } - SHM->Bbusystate = 1; - for (i = 0; i < SHM->Bnumber; i++) { - SHM->bsorted[0][i] = SHM->bsorted[1][i] = i; - } - qsort(SHM->bsorted[0], SHM->Bnumber, sizeof(int), cmpboardname); - qsort(SHM->bsorted[1], SHM->Bnumber, sizeof(int), cmpboardclass); - - for (i = 0; i < SHM->Bnumber; i++) { - bcache[i].firstchild[0] = 0; - bcache[i].firstchild[1] = 0; - } - SHM->Bbusystate = 0; -} - -#ifdef _BBS_UTIL_C_ -void -reload_bcache(void) -{ - int i, fd; - pid_t pid; - for( i = 0 ; i < 10 && SHM->Bbusystate ; ++i ){ - printf("SHM->Bbusystate is currently locked (value: %d). " - "please wait... ", SHM->Bbusystate); - sleep(1); - } - - SHM->Bbusystate = 1; - if ((fd = open(fn_board, O_RDONLY)) > 0) { - SHM->Bnumber = - read(fd, bcache, MAX_BOARD * sizeof(boardheader_t)) / - sizeof(boardheader_t); - close(fd); - } - memset(SHM->lastposttime, 0, MAX_BOARD * sizeof(time4_t)); - memset(SHM->total, 0, MAX_BOARD * sizeof(int)); - - /* µ¥©Ò¦³ boards ¸ê®Æ§ó·s«á¦A³]©w uptime */ - SHM->Buptime = SHM->Btouchtime; - log_usies("CACHE", "reload bcache"); - SHM->Bbusystate = 0; - sort_bcache(); - - printf("load bottom in background"); - if( (pid = fork()) > 0 ) - return; - setproctitle("loading bottom"); - for( i = 0 ; i < MAX_BOARD ; ++i ) - if( SHM->bcache[i].brdname[0] ){ - char fn[128]; - int n; - sprintf(fn, "boards/%c/%s/" FN_DIR ".bottom", - SHM->bcache[i].brdname[0], - SHM->bcache[i].brdname); - n = get_num_records(fn, sizeof(fileheader_t)); - if( n > 5 ) - n = 5; - SHM->n_bottom[i] = n; - } - printf("load bottom done"); - if( pid == 0 ) - exit(0); - // if pid == -1 should be returned -} - -void resolve_boards(void) -{ - while (SHM->Buptime < SHM->Btouchtime) { - reload_bcache(); - } - numboards = SHM->Bnumber; -} -#endif /* defined(_BBS_UTIL_C_)*/ - -#if 0 -/* Unused */ -void touch_boards(void) -{ - SHM->Btouchtime = COMMON_TIME; - numboards = -1; - resolve_boards(); -} -#endif - -void addbrd_touchcache(void) -{ - SHM->Bnumber++; - numboards = SHM->Bnumber; - reset_board(numboards); - sort_bcache(); -} - -void -reset_board(int bid) /* XXXbid: from 1 */ -{ /* Ptt: ³o¼Ë´N¤£¥Î¦Ñ¬Otouch board¤F */ - int fd; - boardheader_t *bhdr; - - if (--bid < 0) - return; - assert(0<=bid && bid<MAX_BOARD); - if (SHM->Bbusystate || COMMON_TIME - SHM->busystate_b[bid] < 10) { - safe_sleep(1); - } else { - SHM->busystate_b[bid] = COMMON_TIME; - - bhdr = bcache; - bhdr += bid; - if ((fd = open(fn_board, O_RDONLY)) > 0) { - lseek(fd, (off_t) (bid * sizeof(boardheader_t)), SEEK_SET); - read(fd, bhdr, sizeof(boardheader_t)); - close(fd); - } - SHM->busystate_b[bid] = 0; - - buildBMcache(bid + 1); /* XXXbid */ - } -} - -#ifndef _BBS_UTIL_C_ /* because of HasBoardPerm() in board.c */ -int -apply_boards(int (*func) (boardheader_t *)) -{ - register int i; - register boardheader_t *bhdr; - - for (i = 0, bhdr = bcache; i < numboards; i++, bhdr++) { - if (!(bhdr->brdattr & BRD_GROUPBOARD) && HasBoardPerm(bhdr) && - (*func) (bhdr) == QUIT) - return QUIT; - } - return 0; -} -#endif - -void -setbottomtotal(int bid) -{ - boardheader_t *bh = getbcache(bid); - char fname[PATHLEN]; - int n; - - assert(0<=bid-1 && bid-1<MAX_BOARD); - if(!bh->brdname[0]) return; - setbfile(fname, bh->brdname, FN_DIR ".bottom"); - n = get_num_records(fname, sizeof(fileheader_t)); - if(n>5) - { -#ifdef DEBUG_BOTTOM - log_file("fix_bottom", LOG_CREAT | LOG_VF, "%s n:%d\n", fname, n); -#endif - unlink(fname); - SHM->n_bottom[bid-1]=0; - } - else - SHM->n_bottom[bid-1]=n; -} -void -setbtotal(int bid) -{ - boardheader_t *bh = getbcache(bid); - struct stat st; - char genbuf[256]; - int num, fd; - - assert(0<=bid-1 && bid-1<MAX_BOARD); - setbfile(genbuf, bh->brdname, FN_DIR); - if ((fd = open(genbuf, O_RDWR)) < 0) - return; /* .DIR±¾¤F */ - fstat(fd, &st); - num = st.st_size / sizeof(fileheader_t); - assert(0<=bid-1 && bid-1<MAX_BOARD); - SHM->total[bid - 1] = num; - - if (num > 0) { - lseek(fd, (off_t) (num - 1) * sizeof(fileheader_t), SEEK_SET); - if (read(fd, genbuf, FNLEN) >= 0) { - SHM->lastposttime[bid - 1] = (time4_t) atoi(&genbuf[2]); - } - } else - SHM->lastposttime[bid - 1] = 0; - close(fd); -} - -void -touchbpostnum(int bid, int delta) -{ - int *total = &SHM->total[bid - 1]; - assert(0<=bid-1 && bid-1<MAX_BOARD); - if (*total) - *total += delta; -} - -int -getbnum(const char *bname) -{ - register int i = 0, j, start = 0, end = SHM->Bnumber - 1; - int *blist = SHM->bsorted[0]; - if(SHM->Bbusystate) - sleep(1); - for (i = ((start + end) / 2);; i = (start + end) / 2) { - if (!(j = strcasecmp(bname, bcache[blist[i]].brdname))) - return (int)(blist[i] + 1); - if (end == start) { - break; - } else if (i == start) { - i = end; - start = end; - } else if (j > 0) - start = i; - else - end = i; - } - return 0; -} - -const char * -postperm_msg(const char *bname) -{ - register int i; - char buf[PATHLEN]; - boardheader_t *bp = NULL; - - setbfile(buf, bname, fn_water); - if (belong(buf, cuser.userid)) - return "¨Ï¥ÎªÌ¤ô±í¤¤"; - - if (!strcasecmp(bname, DEFAULT_BOARD)) - return NULL; - - if (!(i = getbnum(bname))) - return "¬ÝªO¤£¦s¦b"; - - assert(0<=i-1 && i-1<MAX_BOARD); - bp = getbcache(i); - - if (bp->brdattr & BRD_GUESTPOST) - return NULL; - - if (!HasUserPerm(PERM_POST)) - return "µLµo¤åÅv"; - - /* ¯µ±K¬ÝªO¯S§O³B²z */ - if (bp->brdattr & BRD_HIDE) - return NULL; - else if (bp->brdattr & BRD_RESTRICTEDPOST && - !is_hidden_board_friend(i, usernum)) - return "¬ÝªO¨îµo¤å"; - - if (HasUserPerm(PERM_VIOLATELAW) && (bp->level & PERM_VIOLATELAW)) - return NULL; - else if (HasUserPerm(PERM_VIOLATELAW)) - return "»@³æ¥¼Ãº"; - - if (!(bp->level & ~PERM_POST)) - return NULL; - if (!HasUserPerm(bp->level & ~PERM_POST)) - return "¥¼¹F¬ÝªOn¨DÅv"; - return NULL; -} - -int -haspostperm(const char *bname) -{ - return postperm_msg(bname) == NULL ? 1 : 0; -} - -void buildBMcache(int bid) /* bid starts from 1 */ -{ - char s[IDLEN * 3 + 3], *ptr; - int i, uid; - char *strtok_pos; - - assert(0<=bid-1 && bid-1<MAX_BOARD); - strlcpy(s, getbcache(bid)->BM, sizeof(s)); - for( i = 0 ; s[i] != 0 ; ++i ) - if( !isalpha((int)s[i]) && !isdigit((int)s[i]) ) - s[i] = ' '; - - for( ptr = strtok_r(s, " ", &strtok_pos), i = 0 ; - i < MAX_BMs && ptr != NULL ; - ptr = strtok_r(NULL, " ", &strtok_pos), ++i ) - if( (uid = searchuser(ptr, NULL)) != 0 ) - SHM->BMcache[bid-1][i] = uid; - for( ; i < MAX_BMs ; ++i ) - SHM->BMcache[bid-1][i] = -1; -} - -int is_BM_cache(int bid) /* bid starts from 1 */ -{ - assert(0<=bid-1 && bid-1<MAX_BOARD); - --bid; - // XXX hard coded MAX_BMs=4 - if( currutmp->uid == SHM->BMcache[bid][0] || - currutmp->uid == SHM->BMcache[bid][1] || - currutmp->uid == SHM->BMcache[bid][2] || - currutmp->uid == SHM->BMcache[bid][3] ){ - cuser.userlevel |= PERM_BM; - return 1; - } - return 0; -} - -/*-------------------------------------------------------*/ -/* PTT cache */ -/*-------------------------------------------------------*/ -int -filter_aggressive(const char*s) -{ - if ( - /* - strstr(s, "¦¹³B©ñ¸û¤£¾A·íªºª§Ä³©Ê¦r¥y") != NULL || - */ - 0 - ) - return 1; - return 0; -} - -int -filter_dirtywords(const char*s) -{ - if ( - strstr(s, "·F§A®Q") != NULL || - 0) - return 1; - return 0; -} - -#define AGGRESSIVE_FN ".aggressive" -static char drop_aggressive = 0; - -void -load_aggressive_state() -{ - if (dashf(AGGRESSIVE_FN)) - drop_aggressive = 1; - else - drop_aggressive = 0; -} - -void -set_aggressive_state(int s) -{ - FILE *fp = NULL; - if (s) - { - fp = fopen(AGGRESSIVE_FN, "wb"); - fclose(fp); - } else { - remove(AGGRESSIVE_FN); - } -} - -/* cache for °ÊºA¬ÝªO */ -void -reload_pttcache(void) -{ - if (SHM->Pbusystate) - safe_sleep(1); - else { /* jochang: temporary workaround */ - fileheader_t item, subitem; - char pbuf[256], buf[256], *chr; - FILE *fp, *fp1, *fp2; - int id, aggid, rawid; - - SHM->Pbusystate = 1; - SHM->last_film = 0; - bzero(SHM->notes, sizeof(SHM->notes)); - setapath(pbuf, GLOBAL_NOTE); - setadir(buf, pbuf); - - load_aggressive_state(); - id = aggid = rawid = 0; // effective count, aggressive count, total (raw) count - - if ((fp = fopen(buf, "r"))) { - // .DIR loop - while (fread(&item, sizeof(item), 1, fp)) { - - int chkagg = 0; // should we check aggressive? - - if (item.title[3] != '<' || item.title[8] != '>') - continue; - -#ifdef GLOBAL_NOTE_AGGCHKDIR - // TODO aggressive: only count '<ÂIºq>' section - if (strcmp(item.title+3, GLOBAL_NOTE_AGGCHKDIR) == 0) - chkagg = 1; -#endif - - snprintf(buf, sizeof(buf), "%s/%s/" FN_DIR, - pbuf, item.filename); - - if (!(fp1 = fopen(buf, "r"))) - continue; - - // file loop - while (fread(&subitem, sizeof(subitem), 1, fp1)) { - - snprintf(buf, sizeof(buf), - "%s/%s/%s", pbuf, item.filename, - subitem.filename); - - if (!(fp2 = fopen(buf, "r"))) - continue; - - fread(SHM->notes[id], sizeof(char), sizeof(SHM->notes[0]), fp2); - SHM->notes[id][sizeof(SHM->notes[0]) - 1] = 0; - rawid ++; - - // filtering - if (filter_dirtywords(SHM->notes[id])) - { - memset(SHM->notes[id], 0, sizeof(SHM->notes[0])); - rawid --; - } - else if (chkagg && filter_aggressive(SHM->notes[id])) - { - aggid++; - // handle aggressive notes by last detemined state - if (drop_aggressive) - memset(SHM->notes[id], 0, sizeof(SHM->notes[0])); - else - id++; -#ifdef _BBS_UTIL_C_ - // Debug purpose - // printf("found aggressive: %s\n", buf); -#endif - } - else - { - id++; - } - - fclose(fp2); - if (id >= MAX_MOVIE) - break; - - } // end of file loop - fclose(fp1); - - if (id >= MAX_MOVIE) - break; - } // end of .DIR loop - fclose(fp); - - // decide next aggressive state - if (rawid && aggid*3 >= rawid) // if aggressive exceed 1/3 - set_aggressive_state(1); - else - set_aggressive_state(0); - -#ifdef _BBS_UTIL_C_ - printf("id(%d)/agg(%d)/raw(%d)\n", - id, aggid, rawid); -#endif - } - SHM->last_film = id - 1; - - fp = fopen("etc/today_is", "r"); - if (fp) { - fgets(SHM->today_is, 15, fp); - if ((chr = strchr(SHM->today_is, '\n'))) - *chr = 0; - SHM->today_is[15] = 0; - fclose(fp); - } - /* µ¥©Ò¦³¸ê®Æ§ó·s«á¦A³]©w uptime */ - - SHM->Puptime = SHM->Ptouchtime; - log_usies("CACHE", "reload pttcache"); - SHM->Pbusystate = 0; - } -} - -void -resolve_garbage(void) -{ - int count = 0; - - while (SHM->Puptime < SHM->Ptouchtime) { /* ¤£¥Îwhileµ¥ */ - reload_pttcache(); - if (count++ > 10 && SHM->Pbusystate) { - /* - * Ptt: ³oÃä·|¦³°ÝÃD load¶W¹L10 ¬í·|©Ò¦³¶iloopªºprocess tate = 0 - * ³o¼Ë·|©Ò¦³prcosee³£·|¦bload °ÊºA¬ÝªO ·|³y¦¨load¤j¼W - * ¦ý¨S¦³¥Î³oÓfunctionªº¸Ü ¸U¤@load passwdÀɪºprocess¦º¤F - * ¤S¨S¦³¤H§â¥L ¸Ñ¶} ¦P¼Ëªº°ÝÃDµo¥Í¦breload passwd - */ - SHM->Pbusystate = 0; -#ifndef _BBS_UTIL_C_ - log_usies("CACHE", "refork Ptt dead lock"); -#endif - } - } -} - -/*-------------------------------------------------------*/ -/* PTT's cache */ -/*-------------------------------------------------------*/ -/* cache for from host »P³Ì¦h¤W½u¤H¼Æ */ -void -reload_fcache(void) -{ - if (SHM->Fbusystate) - safe_sleep(1); - else { - FILE *fp; - - SHM->Fbusystate = 1; - bzero(SHM->home_ip, sizeof(SHM->home_ip)); - if ((fp = fopen("etc/domain_name_query.cidr", "r"))) { - char buf[256], *ip, *mask; - char *strtok_pos; - - SHM->home_num = 0; - while (fgets(buf, sizeof(buf), fp)) { - if (!buf[0] || buf[0] == '#' || buf[0] == ' ' || buf[0] == '\n') - continue; - - if (buf[0] == '@') { - SHM->home_ip[0] = 0; - SHM->home_mask[0] = 0xFFFFFFFF; - SHM->home_num++; - continue; - } - - ip = strtok_r(buf, " \t", &strtok_pos); - if ((mask = strchr(ip, '/')) != NULL) { - int shift = 32 - atoi(mask + 1); - SHM->home_ip[SHM->home_num] = ipstr2int(ip); - SHM->home_mask[SHM->home_num] = (0xFFFFFFFF >> shift ) << shift; - } - else { - SHM->home_ip[SHM->home_num] = ipstr2int(ip); - SHM->home_mask[SHM->home_num] = 0xFFFFFFFF; - } - ip = strtok_r(NULL, " \t", &strtok_pos); - if (ip == NULL) { - strcpy(SHM->home_desc[SHM->home_num], "¶³²`¤£ª¾³B"); - } - else { - strlcpy(SHM->home_desc[SHM->home_num], ip, - sizeof(SHM->home_desc[SHM->home_num])); - chomp(SHM->home_desc[SHM->home_num]); - } - (SHM->home_num)++; - if (SHM->home_num == MAX_FROM) - break; - } - fclose(fp); - } - SHM->max_user = 0; - - /* µ¥©Ò¦³¸ê®Æ§ó·s«á¦A³]©w uptime */ - SHM->Fuptime = SHM->Ftouchtime; -#if !defined(_BBS_UTIL_C_) - log_usies("CACHE", "reload fcache"); -#endif - SHM->Fbusystate = 0; - } -} - -void -resolve_fcache(void) -{ - while (SHM->Fuptime < SHM->Ftouchtime) - reload_fcache(); -} - -/* - * section - hbfl (hidden board friend list) - */ -void -hbflreload(int bid) -{ - int hbfl[MAX_FRIEND + 1], i, num, uid; - char buf[128]; - FILE *fp; - - assert(0<=bid-1 && bid-1<MAX_BOARD); - memset(hbfl, 0, sizeof(hbfl)); - setbfile(buf, bcache[bid - 1].brdname, fn_visable); - if ((fp = fopen(buf, "r")) != NULL) { - for (num = 1; num <= MAX_FRIEND; ++num) { - if (fgets(buf, sizeof(buf), fp) == NULL) - break; - for (i = 0; buf[i] != 0; ++i) - if (buf[i] == ' ') { - buf[i] = 0; - break; - } - if (strcasecmp(STR_GUEST, buf) == 0 || - (uid = searchuser(buf, NULL)) == 0) { - --num; - continue; - } - hbfl[num] = uid; - } - fclose(fp); - } - hbfl[0] = COMMON_TIME; - memcpy(SHM->hbfl[bid-1], hbfl, sizeof(hbfl)); -} - -/* ¬O§_³q¹LªO¤Í´ú¸Õ. ¦pªG¦bªO¤Í¦W³æ¤¤ªº¸Ü¶Ç¦^ 1, §_«h¬° 0 */ -int -is_hidden_board_friend(int bid, int uid) -{ - int i; - - assert(0<=bid-1 && bid-1<MAX_BOARD); - if (SHM->hbfl[bid-1][0] < login_start_time - HBFLexpire) - hbflreload(bid); - for (i = 1; SHM->hbfl[bid-1][i] != 0 && i <= MAX_FRIEND; ++i) { - if (SHM->hbfl[bid-1][i] == uid) - return 1; - } - return 0; -} - -#ifdef USE_COOLDOWN -void add_cooldowntime(int uid, int min) -{ - // Ptt: I will use the number below 15 seconds. - time4_t base= now > SHM->cooldowntime[uid - 1]? - now : SHM->cooldowntime[uid - 1]; - base += min*60; - base &= 0xFFFFFFF0; - - SHM->cooldowntime[uid - 1] = base; -} -void add_posttimes(int uid, int times) -{ - if((SHM->cooldowntime[uid - 1] & 0xF) + times <0xF) - SHM->cooldowntime[uid - 1] += times; - else - SHM->cooldowntime[uid - 1] |= 0xF; -} -#endif diff --git a/mbbsd/cal.c b/mbbsd/cal.c deleted file mode 100644 index 1f6f9d9d..00000000 --- a/mbbsd/cal.c +++ /dev/null @@ -1,630 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -/* ¨¾°ô Multi play */ -static int -is_playing(int unmode) -{ - register int i; - register userinfo_t *uentp; - unsigned int p = StringHash(cuser.userid) % USHM_SIZE; - - for (i = 0; i < USHM_SIZE; i++, p++) { // XXX linear search - if (p == USHM_SIZE) - p = 0; - uentp = &(SHM->uinfo[p]); - if (uentp->uid == usernum) - if (uentp->lockmode == unmode) - return 1; - } - return 0; -} - -int -lockutmpmode(int unmode, int state) -{ - int errorno = 0; - - if (currutmp->lockmode) - errorno = LOCK_THIS; - else if (state == LOCK_MULTI && is_playing(unmode)) - errorno = LOCK_MULTI; - - if (errorno) { - clear(); - move(10, 20); - if (errorno == LOCK_THIS) - prints("½Ð¥ýÂ÷¶} %s ¤~¯à¦A %s ", - ModeTypeTable[currutmp->lockmode], - ModeTypeTable[unmode]); - else - prints("©êºp! ±z¤w¦³¨ä¥L½u¬Û¦PªºID¥¿¦b%s", - ModeTypeTable[unmode]); - pressanykey(); - return errorno; - } - setutmpmode(unmode); - currutmp->lockmode = unmode; - return 0; -} - -int -unlockutmpmode(void) -{ - currutmp->lockmode = 0; - return 0; -} - -/* ¨Ï¥Î¿úªº¨ç¼Æ */ -#define VICE_NEW "vice.new" - -/* Heat:µo²¼ */ -int -vice(int money, const char *item) -{ - char buf[128]; - unsigned int viceserial = (currutmp->lastact % 10000) * 10000 + - random() % 10000; - - // new logic: do not send useless vice tickets - demoney(-money); - if (money < VICE_MIN) - return 0; - - setuserfile(buf, VICE_NEW); - log_filef(buf, LOG_CREAT, "%8.8d\n", viceserial); - snprintf(buf, sizeof(buf), - "%s ªá¤F$%d ½s¸¹[%08d]", item, money, viceserial); - mail_id(cuser.userid, buf, "etc/vice.txt", BBSMNAME "¸gÀÙ³¡"); - return 0; -} - -#define lockreturn(unmode, state) if(lockutmpmode(unmode, state)) return -#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 -#define lockbreak(unmode, state) if(lockutmpmode(unmode, state)) break -#define SONGBOOK "etc/SONGBOOK" -#define OSONGPATH "etc/SONGO" - -static int -osong(void) -{ - char sender[IDLEN + 1], receiver[IDLEN + 1], buf[200], - genbuf[200], filename[256], say[51]; - char trans_buffer[PATHLEN]; - char address[45]; - FILE *fp, *fp1; - //*fp2; - fileheader_t mail; - int nsongs; - - strlcpy(buf, Cdatedate(&now), sizeof(buf)); - - lockreturn0(OSONG, LOCK_MULTI); - - /* Jaky ¤@¤H¤@¤ÑÂI¤@º */ - if (!strcmp(buf, Cdatedate(&cuser.lastsong)) && !HasUserPerm(PERM_SYSOP)) { - move(22, 0); - vmsg("§A¤µ¤Ñ¤w¸gÂI¹LÅo¡A©ú¤Ñ¦AÂI§a...."); - unlockutmpmode(); - return 0; - } - - while (1) { - char ans[4]; - move(12, 0); - clrtobot(); - prints("¿Ë·Rªº %s Åwªï¨Ó¨ì¼Ú®á¦Û°ÊÂIºq¨t²Î\n\n", cuser.userid); - outs(ANSI_COLOR(1) "ª`·NÂIºq¤º®e½Ð¤Å¯A¤Îðã½| ¤H¨§ðÀ» µTÁ¶" - "¤½µM«V°d ½ÚÁ½\n" - "Y¦³¤Wz¹H³W±¡§Î¡A¯¸¤è±N«O¯d¨M©w¬O§_¤½¶}¼½©ñªºÅv§Q\n" - "¦p¤£¦P·N½Ð«ö (3) Â÷¶}¡C" ANSI_RESET "\n"); - getdata(18, 0, "½Ð¿ï¾Ü " ANSI_COLOR(1) "1)" ANSI_RESET " ¶}©lÂIºq¡B" - ANSI_COLOR(1) "2)" ANSI_RESET " ¬Ýºq¥»¡B" - "©Î¬O " ANSI_COLOR(1) "3)" ANSI_RESET " Â÷¶}: ", - ans, sizeof(ans), DOECHO); - - if (ans[0] == '1') - break; - else if (ans[0] == '2') { - a_menu("ÂIºqºq¥»", SONGBOOK, 0, 0, NULL); - clear(); - } - else if (ans[0] == '3') { - vmsg("ÁÂÁÂ¥úÁ{ :)"); - unlockutmpmode(); - return 0; - } - } - - if (cuser.money < 200) { - move(22, 0); - vmsg("ÂIºqn200»Èò!...."); - unlockutmpmode(); - return 0; - } - - getdata_str(19, 0, "ÂIºqªÌ(¥i°Î¦W): ", sender, sizeof(sender), DOECHO, cuser.userid); - getdata(20, 0, "ÂIµ¹(¥i°Î¦W): ", receiver, sizeof(receiver), DOECHO); - - getdata_str(21, 0, "·Qnn¹ï¥L(¦o)»¡..:", say, - sizeof(say), DOECHO, "§Ú·R©p.."); - snprintf(save_title, sizeof(save_title), - "%s:%s", sender, say); - getdata_str(22, 0, "±H¨ì½Öªº«H½c(¯u¹ê ID ©Î E-mail)?", - address, sizeof(address), LCECHO, receiver); - vmsg("±µµÛn¿ïºqÅo..¶i¤Jºq¥»¦n¦nªº¿ï¤@ººq§a..^o^"); - a_menu("ÂIºqºq¥»", SONGBOOK, 0, 0, trans_buffer); - if (!trans_buffer[0] || strstr(trans_buffer, "home") || - strstr(trans_buffer, "boards") || !(fp = fopen(trans_buffer, "r"))) { - unlockutmpmode(); - return 0; - } - strlcpy(filename, OSONGPATH, sizeof(filename)); - - stampfile(filename, &mail); - - unlink(filename); - - if (!(fp1 = fopen(filename, "w"))) { - fclose(fp); - unlockutmpmode(); - return 0; - } - strlcpy(mail.owner, "ÂIºq¾÷", sizeof(mail.owner)); - snprintf(mail.title, sizeof(mail.title), "¡º %s ÂIµ¹ %s ", sender, receiver); - - while (fgets(buf, sizeof(buf), fp)) { - char *po; - if (!strncmp(buf, "¼ÐÃD: ", 6)) { - clear(); - move(10, 10); - outs(buf); - pressanykey(); - fclose(fp); - fclose(fp1); - unlockutmpmode(); - return 0; - } - while ((po = strstr(buf, "<~Src~>"))) { - const char *dot = ""; - if (is_validuserid(sender) && strcmp(sender, cuser.userid) != 0) - dot = "."; - po[0] = 0; - snprintf(genbuf, sizeof(genbuf), "%s%s%s%s", buf, sender, dot, po + 7); - strlcpy(buf, genbuf, sizeof(buf)); - } - while ((po = strstr(buf, "<~Des~>"))) { - po[0] = 0; - snprintf(genbuf, sizeof(genbuf), "%s%s%s", buf, receiver, po + 7); - strlcpy(buf, genbuf, sizeof(buf)); - } - while ((po = strstr(buf, "<~Say~>"))) { - po[0] = 0; - snprintf(genbuf, sizeof(genbuf), "%s%s%s", buf, say, po + 7); - strlcpy(buf, genbuf, sizeof(buf)); - } - fputs(buf, fp1); - } - fclose(fp1); - fclose(fp); - - log_filef("etc/osong.log", LOG_CREAT, "id: %-12s ¡º %s ÂIµ¹ %s : \"%s\", Âà±H¦Ü %s\n", cuser.userid, sender, receiver, say, address); - - if (append_record(OSONGPATH "/" FN_DIR, &mail, sizeof(mail)) != -1) { - cuser.lastsong = now; - /* Jaky ¶W¹L MAX_MOVIE ººq´N¶}©l¬å */ - nsongs = get_num_records(OSONGPATH "/" FN_DIR, sizeof(mail)); - if (nsongs > MAX_MOVIE) { - // XXX race condition - delete_range(OSONGPATH "/" FN_DIR, 1, nsongs - MAX_MOVIE); - } - snprintf(genbuf, sizeof(genbuf), "%s says \"%s\" to %s.", sender, say, receiver); - log_usies("OSONG", genbuf); - /* §â²Ä¤@º®³±¼ */ - vice(200, "ÂIºq"); - } - snprintf(save_title, sizeof(save_title), "%s:%s", sender, say); - hold_mail(filename, receiver); - - if (address[0]) { -#ifndef USE_BSMTP - bbs_sendmail(filename, save_title, address); -#else - bsmtp(filename, save_title, address); -#endif - } - clear(); - outs( - "\n\n ®¥³ß±zÂIºq§¹¦¨Åo..\n" - " ¤@¤p®É¤º°ÊºA¬ÝªO·|¦Û°Ê«·s§ó·s\n" - " ¤j®a´N¥i¥H¬Ý¨ì±zÂIªººqÅo\n\n" - " ÂIºq¦³¥ô¦ó°ÝÃD¥i¥H¨ìNoteªOªººëµØ°Ï§äµª®×\n" - " ¤]¥i¦bNoteªOºëµØ°Ï¬Ý¨ì¦Û¤vªºÂIºq°O¿ý\n" - " ¦³¥ô¦ó«O¶Qªº·N¨£¤]Åwªï¨ìNoteªO¯d¸Ü\n" - " Åý¿Ë¤ÁªºªO¥D¬°±zªA°È\n"); - pressanykey(); - sortsong(); - topsong(); - - unlockutmpmode(); - return 1; -} - -int -ordersong(void) -{ - osong(); - return 0; -} - -static int -inmailbox(int m) -{ - userec_t xuser; - passwd_query(usernum, &xuser); - cuser.exmailbox = xuser.exmailbox + m; - passwd_update(usernum, &cuser); - return cuser.exmailbox; -} - - -#if !HAVE_FREECLOAK -/* ªá¿ú¿ï³æ */ -int -p_cloak(void) -{ - if (getans(currutmp->invisible ? "½T©wn²{¨?[y/N]" : "½T©wnÁô¨?[y/N]") != 'y') - return 0; - if (cuser.money >= 19) { - vice(19, "¥I¶OÁô¨"); - currutmp->invisible %= 2; - vmsg((currutmp->invisible ^= 1) ? MSG_CLOAKED : MSG_UNCLOAK); - } - return 0; -} -#endif - -int -p_from(void) -{ - char tmp_from[sizeof(currutmp->from)]; - if (getans("½T©wn§ï¬G¶m?[y/N]") != 'y') - return 0; - reload_money(); - if (cuser.money < 49) - return 0; - if (getdata_buf(b_lines - 1, 0, "½Ð¿é¤J·s¬G¶m:", - tmp_from, sizeof(tmp_from), DOECHO)) { - vice(49, "§ó§ï¬G¶m"); - strlcpy(currutmp->from, tmp_from, sizeof(currutmp->from)); - currutmp->from_alias = 0; - } - return 0; -} - -int -p_exmail(void) -{ - char ans[4], buf[200]; - int n; - - if (cuser.exmailbox >= MAX_EXKEEPMAIL) { - vmsgf("®e¶q³Ì¦h¼W¥[ %d «Ê¡A¤£¯à¦A¶R¤F¡C", MAX_EXKEEPMAIL); - return 0; - } - snprintf(buf, sizeof(buf), - "±z´¿¼WÁÊ %d «Ê®e¶q¡AÁÙn¦A¶R¦h¤Ö? ", cuser.exmailbox); - - // no need to create default prompt. - // and people usually come this this by accident... - getdata(b_lines - 2, 0, buf, ans, sizeof(ans), LCECHO); - - n = atoi(ans); - if (!ans[0] || n<=0) - return 0; - - if (n + cuser.exmailbox > MAX_EXKEEPMAIL) - n = MAX_EXKEEPMAIL - cuser.exmailbox; - reload_money(); - if (cuser.money < n * 1000) - { - vmsg("§Aªº¿ú¤£°÷¡C"); - return 0; - } - - if (vmsgf("§A·QÁʶR %d «Ê«H½c (nªá %d ¤¸), ½T©w¶Ü¡H[y/N] ", - n, n*1000) != 'y') - return 0; - - vice(n * 1000, "ÁʶR«H½c"); - inmailbox(n); - vmsgf("¤wÁʶR«H½c¡C·s®e¶q¤W: %d", cuser.exmailbox); - return 0; -} - -void -mail_redenvelop(const char *from, const char *to, int money, char mode) -{ - char genbuf[200]; - fileheader_t fhdr; - FILE *fp; - - sethomepath(genbuf, to); - stampfile(genbuf, &fhdr); - if (!(fp = fopen(genbuf, "w"))) - return; - fprintf(fp, "§@ªÌ: %s\n" - "¼ÐÃD: ©Û°]¶iÄ_\n" - "®É¶¡: %s\n" - ANSI_COLOR(1;33) "¿Ë·Rªº %s ¡G\n\n" ANSI_RESET - ANSI_COLOR(1;31) " §Ú¥]µ¹§A¤@Ó %d ¤¸ªº¤j¬õ¥]³á ^_^\n\n" - " §»´±¡·N«¡A½Ð¯º¯Ç...... ^_^" ANSI_RESET "\n", - from, ctime4(&now), to, money); - fclose(fp); - snprintf(fhdr.title, sizeof(fhdr.title), "©Û°]¶iÄ_"); - strlcpy(fhdr.owner, from, sizeof(fhdr.owner)); - - if (mode == 'y') - vedit(genbuf, NA, NULL); - sethomedir(genbuf, to); - append_record(genbuf, &fhdr, sizeof(fhdr)); -} - - -int do_give_money(char *id, int uid, int money) -{ - int tax; -#ifdef PLAY_ANGEL - userec_t xuser; -#endif - - reload_money(); - if (money > 0 && cuser.money >= money) { - tax = give_tax(money); - if (money - tax <= 0) - return -1; /* ú§¹µ|´N¨S¿úµ¹¤F */ - deumoney(uid, money - tax); - demoney(-money); - log_filef(FN_MONEY, LOG_CREAT, "%-12s µ¹ %-12s %d\t(µ|«á %d)\t%s", - cuser.userid, id, money, money - tax, ctime4(&now)); -#ifdef PLAY_ANGEL - getuser(id, &xuser); - if (!strcmp(xuser.myangel, cuser.userid)){ - mail_redenvelop( - getkey("¥L¬O§Aªº¤p¥D¤H¡A¬O§_°Î¦W¡H[Y/n]") == 'n' ? - cuser.userid : "¤p¤Ñ¨Ï", id, money - tax, - getans("n¦Û¦æ®Ñ¼g¬õ¥]³U¶Ü¡H[y/N]")); - } else -#endif - mail_redenvelop(cuser.userid, id, money - tax, - getans("n¦Û¦æ®Ñ¼g¬õ¥]³U¶Ü¡H[y/N]")); - if (money < 50) { - usleep(2000000); - } else if (money < 200) { - usleep(500000); - } else { - usleep(100000); - } - return 0; - } - return -1; -} - -int -p_give(void) -{ - give_money_ui(NULL); - return -1; -} - -int -give_money_ui(const char *userid) -{ - int uid; - char id[IDLEN + 1], money_buf[20]; - char passbuf[PASSLEN]; - int m = 0, tries = 3, skipauth = 0; - static time4_t lastauth = 0; - - // TODO prevent macros, we should check something here, - // like user pw/id/... - clear(); - stand_title("µ¹¤©ª÷¿ú"); - if (!userid || !*userid) - usercomplete("³o¦ì©¯¹B¨àªºid: ", id); - else { - strlcpy(id, userid, sizeof(id)); - prints("³o¦ì©¯¹B¨àªºid: %s\n", id); - } - move(2, 0); clrtobot(); - - if (!id[0] || !strcasecmp(cuser.userid, id)) - { - vmsg("¥æ©ö¨ú®ø!"); - return -1; - } - if (!getdata(2, 0, "nµ¹¥L¦h¤Ö¿ú©O: ", money_buf, 7, LCECHO) || - ((m = atoi(money_buf)) <= 0)) - { - vmsg("¥æ©ö¨ú®ø!"); - return -1; - } - if ((uid = searchuser(id, id)) == 0) { - vmsg("¬dµL¦¹¤H!"); - return -1; - } - move(4, 0); - prints("¥æ©ö¤º®e: %s ±Nµ¹¤© %s : %d ¤¸ (n¦A¦©µ|ª÷ %d ¤¸)\n", - cuser.userid, id, m, give_tax(m)); - - if (now - lastauth >= 15*60) // valid through 15 minutes - { - outs(ANSI_COLOR(1;31) "¬°¤FÁקK»~«ö©Î¬O´c·N¶BÄF¡A" - "¦b§¹¦¨¥æ©ö«en«·s½T»{±zªº¨¥÷¡C" ANSI_RESET); - } else { - outs("§Aªº»{ÃÒ©|¥¼¹L´Á¡A¥i¼È®É¸õ¹L±K½X»{ÃÒµ{§Ç¡C\n"); - // auth is valid. - if (getans("½T©w¶i¦æ¥æ©ö¶Ü¡H (y/N): ") == 'y') - skipauth = 1; - else - tries = -1; - } - - while (!skipauth && tries-- > 0) - { - getdata(6, 0, MSG_PASSWD, - passbuf, sizeof(passbuf), NOECHO); - passbuf[8] = '\0'; - if (checkpasswd(cuser.passwd, passbuf)) - { - lastauth = now; - break; - } - if (tries > 0) - vmsgf("±K½X¿ù»~¡AÁÙ¦³ %d ¦¸¾÷·|¡C", tries); - } - if (tries < 0) - { - vmsg("¥æ©ö¨ú®ø!"); - return -1; - } - // vmsg("·Ç³Æ¥æ©ö¡C"); - // return -1; - return do_give_money(id, uid, m); -} - -void -resolve_over18(void) -{ - /* get local time */ - struct tm ptime = *localtime4(&now); - - over18 = 0; - /* check if over18 */ - // ·Ó¹ê·³pºâ¡A¨S¥Í¤éªº·í§@¥¼º¡ 18 - if (cuser.year < 1 || cuser.month < 1) - over18 = 0; - else if( (ptime.tm_year - cuser.year) > 18) - over18 = 1; - else if (ptime.tm_year - cuser.year < 18) - over18 = 0; - else if ((ptime.tm_mon+1) > cuser.month) - over18 = 1; - else if ((ptime.tm_mon+1) < cuser.month) - over18 = 0; - else if (ptime.tm_mday >= cuser.day ) - over18 = 1; -} - -int -p_sysinfo(void) -{ - char *cpuloadstr; - int load; - extern char *compile_time; -#ifdef DETECT_CLIENT - extern Fnv32_t client_code; -#endif - - load = cpuload(NULL); - cpuloadstr = (load < 5 ? "¨}¦n" : (load < 20 ? "©|¥i" : "¹L«")); - - clear(); - showtitle("¨t²Î¸ê°T", BBSNAME); - move(2, 0); - prints("±z²{¦b¦ì©ó " TITLE_COLOR BBSNAME ANSI_RESET " (" MYIP ")\n" - "¨t²Ît¸ü±¡ªp: %s\n" - "½u¤WªA°È¤H¼Æ: %d/%d\n" -#ifdef DETECT_CLIENT - "client code: %8.8X\n" -#endif - "½sĶ®É¶¡: %s\n" - "°_©l®É¶¡: %s\n", - cpuloadstr, SHM->UTMPnumber, -#ifdef DYMAX_ACTIVE - SHM->GV2.e.dymaxactive > 2000 ? SHM->GV2.e.dymaxactive : MAX_ACTIVE, -#else - MAX_ACTIVE, -#endif -#ifdef DETECT_CLIENT - client_code, -#endif - compile_time, ctime4(&start_time)); - -#ifdef REPORT_PIAIP_MODULES - outs("\n" ANSI_COLOR(1;30) - "Modules powered by piaip:\n" - "\ttelnet protocol, ALOHA fixer, BRC v3\n" -#if defined(USE_PIAIP_MORE) || defined(USE_PMORE) - "\tpmore (piaip's more) 2007 w/Movie\n" -#endif -#ifdef HAVE_GRAYOUT - "\tGrayout Advanced Control ²H¤J²H¥X¯S®Ä¨t²Î\n" -#endif -#ifdef EDITPOST_SMARTMERGE - "\tSmart Merge פå¦Û°Ê¦X¨Ö\n" -#endif -#ifdef EXP_EDIT_UPLOAD - "\t(EXP) Editor Uploader ªø¤å¤W¶Ç\n" -#endif -#if defined(USE_PFTERM) - "\t(EXP) pfterm (piaip's flat terminal, Perfect Term)\n" -#endif -#if defined(USE_BBSLUA) - "\t(EXP) BBS-Lua\n" -#endif - ANSI_RESET - ); -#endif // REPORT_PIAIP_MODULES - - if (HasUserPerm(PERM_SYSOP)) { - struct rusage ru; -#ifdef __linux__ - int vmdata=0, vmstk=0; - FILE * fp; - char buf[128]; - if ((fp = fopen("/proc/self/status", "r"))) { - while (fgets(buf, 128, fp)) { - sscanf(buf, "VmData: %d", &vmdata); - sscanf(buf, "VmStk: %d", &vmstk); - } - fclose(fp); - } -#endif - getrusage(RUSAGE_SELF, &ru); - prints("°O¾ÐÅé¥Î¶q: " -#ifdef IA32 - "sbrk: %u KB, " -#endif -#ifdef __linux__ - "VmData: %d KB, VmStk: %d KB, " -#endif - "idrss: %d KB, isrss: %d KB\n", -#ifdef IA32 - ((unsigned int)sbrk(0) - 0x8048000) / 1024, -#endif -#ifdef __linux__ - vmdata, vmstk, -#endif - (int)ru.ru_idrss, (int)ru.ru_isrss); - prints("CPU ¥Î¶q: %ld.%06ldu %ld.%06lds", - (long int)ru.ru_utime.tv_sec, - (long int)ru.ru_utime.tv_usec, - (long int)ru.ru_stime.tv_sec, - (long int)ru.ru_stime.tv_usec); -#ifdef CPULIMIT - prints(" (limit %d secs)", (int)(CPULIMIT * 60)); -#endif - outs("\n¯S§O°Ñ¼Æ:" -#ifdef CRITICAL_MEMORY - " CRITICAL_MEMORY" -#endif -#ifdef OUTTACACHE - " OUTTACACHE" -#endif - ); - } - pressanykey(); - return 0; -} - diff --git a/mbbsd/calendar.c b/mbbsd/calendar.c deleted file mode 100644 index b87c774a..00000000 --- a/mbbsd/calendar.c +++ /dev/null @@ -1,362 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -typedef struct event_t { - int year, month, day, days; - int color; - char *content; - struct event_t *next; -} event_t; - -static int -MonthDay(int m, int leap) -{ - int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - - assert(1<=m && m<=12); - return leap && m == 2 ? 29 : day[m - 1]; -} - -static int -Days(int y, int m, int d) -{ - int i, w; - - w = 1 + 365 * (y - 1) - + ((y - 1) / 4) - ((y - 1) / 100) + ((y - 1) / 400) - + d - 1; - for (i = 1; i < m; i++) - w += MonthDay(i, is_leap_year(y)); - return w; -} - -/** - * return 1 if date is invalid - */ -int ParseDate(const char *date, int *year, int *month, int *day) -{ - char *y, *m, *d; - char buf[128]; - char *strtok_pos; - - strlcpy(buf, date, sizeof(buf)); - y = strtok_r(buf, "/", &strtok_pos); if (!y) return 1; - m = strtok_r(NULL, "/", &strtok_pos);if (!m) return 1; - d = strtok_r(NULL, "", &strtok_pos); if (!d) return 1; - - *year = atoi(y); - *month = atoi(m); - *day = atoi(d); - if (*year < 1 || *month < 1 || *month > 12 || - *day < 1 || *day > MonthDay(*month, is_leap_year(*year))) - return 1; - return 0; -} - -/** - * return 1 if date is invalid - */ -static int -ParseEventDate(const char *date, event_t * t) -{ - int retval = ParseDate(date, &t->year, &t->month, &t->day); - if (retval) - return retval; - t->days = Days(t->year, t->month, t->day); - return retval; -} - -static int -ParseColor(const char *color) -{ - struct { - char *str; - int val; - } c[] = { - { - "black", 0 - }, - { - "red", 1 - }, - { - "green", 2 - }, - { - "yellow", 3 - }, - { - "blue", 4 - }, - { - "magenta", 5 - }, - { - "cyan", 6 - }, - { - "white", 7 - } - }; - int i; - - for (i = 0; (unsigned)i < sizeof(c) / sizeof(c[0]); i++) - if (strcasecmp(color, c[i].str) == 0) - return c[i].val; - return 7; -} - -static void -InsertEvent(event_t * head, event_t * t) -{ - event_t *p; - - for (p = head; p->next && p->next->days < t->days; p = p->next); - t->next = p->next; - p->next = t; -} - -static void -FreeEvent(event_t * e) -{ - event_t *n; - - while (e) { - n = e->next; - free(e->content); /* from strdup() */ - free(e); - e = n; - } -} - -static event_t * -ReadEvent(int today) -{ - FILE *fp; - char buf[256]; - static event_t head; - - head.next = NULL; - sethomefile(buf, cuser.userid, "calendar"); - fp = fopen(buf, "r"); - if (fp) { - while (fgets(buf, sizeof(buf), fp)) { - char *date, *color, *content; - event_t *t; - char *strtok_pos; - - if (buf[0] == '#') - continue; - - date = strtok_r(buf, " \t\n", &strtok_pos); - color = strtok_r(NULL, " \t\n", &strtok_pos); - content = strtok_r(NULL, "\n", &strtok_pos); - if (!date || !color || !content) - continue; - - t = malloc(sizeof(event_t)); - if (ParseEventDate(date, t) || t->days < today) { - free(t); - continue; - } - t->color = ParseColor(color) + 30; - for (; *content == ' ' || *content == '\t'; content++); - t->content = strdup(content); - InsertEvent(&head, t); - } - fclose(fp); - } - return head.next; -} - -static char ** -AllocCalBuffer(int line, int len) -{ - int i; - char **p; - - p = malloc(sizeof(char *) * line); - p[0] = malloc(sizeof(char) * line * len); - for (i = 1; i < line; i++) - p[i] = p[i - 1] + len; - return p; -} - -static void -FreeCalBuffer(char **buf) -{ - free(buf[0]); - free(buf); -} - -#define CALENDAR_COLOR ANSI_COLOR(0;30;47) -#define HEADER_COLOR ANSI_COLOR(1;44) -#define HEADER_SUNDAY_COLOR ANSI_COLOR(31) -#define HEADER_DAY_COLOR ANSI_COLOR(33) - -static int -GenerateCalendar(char **buf, int y, int m, int today, event_t * e) -{ - char *week_str[7] = {"¤é", "¤@", "¤G", "¤T", "¥|", "¤", "¤»"}; - char *month_color[12] = { - ANSI_COLOR(1;32), ANSI_COLOR(1;33), ANSI_COLOR(1;35), ANSI_COLOR(1;36), - ANSI_COLOR(1;32), ANSI_COLOR(1;33), ANSI_COLOR(1;35), ANSI_COLOR(1;36), - ANSI_COLOR(1;32), ANSI_COLOR(1;33), ANSI_COLOR(1;35), ANSI_COLOR(1;36) - }; - char *month_str[12] = { - "¤@¤ë ", "¤G¤ë ", "¤T¤ë ", "¥|¤ë ", "¤¤ë ", "¤»¤ë ", - "¤C¤ë ", "¤K¤ë ", "¤E¤ë ", "¤Q¤ë ", "¤Q¤@¤ë", "¤Q¤G¤ë" - }; - - char *p, attr1[16], *attr2; - int i, d, w, line = 0, first_day = Days(y, m, 1); - - - /* week day banner */ - p = buf[line]; - p += sprintf(p, " %s%s%s%s", HEADER_COLOR, HEADER_SUNDAY_COLOR, - week_str[0], HEADER_DAY_COLOR); - for (i = 1; i < 7; i++) - p += sprintf(p, " %s", week_str[i]); - p += sprintf(p, ANSI_RESET); - - /* indent for first line */ - p = buf[++line]; - p += sprintf(p, " %s", CALENDAR_COLOR); - for (i = 0, w = first_day % 7; i < w; i++) - p += sprintf(p, " "); - - /* initial event */ - for (; e && e->days < first_day; e = e->next); - - d = MonthDay(m, is_leap_year(y)); - for (i = 1; i <= d; i++, w = (w + 1) % 7) { - attr1[0] = 0; - attr2 = ""; - while (e && e->days == first_day + i - 1) { - sprintf(attr1, ANSI_COLOR(1;%d), e->color); - attr2 = CALENDAR_COLOR; - e = e->next; - } - if (today == first_day + i - 1) { - strlcpy(attr1, ANSI_COLOR(1;37;42), sizeof(attr1)); - attr2 = CALENDAR_COLOR; - } - p += sprintf(p, "%s%2d%s", attr1, i, attr2); - - if (w == 6) { - p += sprintf(p, ANSI_RESET); - p = buf[++line]; - /* show month */ - if (line >= 2 && line <= 4) - p += sprintf(p, "%s%2.2s\33[m %s", month_color[m - 1], - month_str[m - 1] + (line - 2) * 2, - CALENDAR_COLOR); - else if (i < d) - p += sprintf(p, " %s", CALENDAR_COLOR); - } else - *p++ = ' '; - } - - /* fill up the last line */ - if (w) { - for (w = 7 - w; w; w--) - p += sprintf(p, w == 1 ? " " : " "); - p += sprintf(p, ANSI_RESET); - } - return line + 1; -} - -int -u_editcalendar(void) -{ - char genbuf[200]; - - getdata(b_lines - 1, 0, "¦æ¨Æ¾ä (D)§R°£ (E)½s¿è (H)»¡©ú [Q]¨ú®ø¡H[Q] ", - genbuf, 3, LCECHO); - - if (genbuf[0] == 'e') { - int aborted; - - setutmpmode(EDITPLAN); - sethomefile(genbuf, cuser.userid, "calendar"); - aborted = vedit(genbuf, NA, NULL); - if (aborted != -1) - vmsg("¦æ¨Æ¾ä§ó·s§¹²¦"); - return 0; - } else if (genbuf[0] == 'd') { - sethomefile(genbuf, cuser.userid, "calendar"); - unlink(genbuf); - vmsg("¦æ¨Æ¾ä§R°£§¹²¦"); - } else if (genbuf[0] == 'h') { - move(1, 0); - clrtoln(b_lines); - move(3, 0); - prints("¦æ¨Æ¾ä®æ¦¡»¡©ú:\n½s¿è®É¥H¤@¦æ¬°³æ¦ì¡A¦p:\n\n# ¤«¸¹¶}ÀYªº¬Oµù¸Ñ\n2006/05/04 red ¤W§å½ð½ð!\n\n¨ä¤¤ªº red ¬O«üªí¥ÜªºÃC¦â¡C"); - pressanykey(); - } - return 0; -} - -int -calendar(void) -{ - char **buf; - struct tm snow; - int i, y, m, today, lines = 0; - event_t *head = NULL, *e = NULL; - - /* initialize date */ - memcpy(&snow, localtime4(&now), sizeof(struct tm)); - today = Days(snow.tm_year + 1900, snow.tm_mon + 1, snow.tm_mday); - y = snow.tm_year + 1900, m = snow.tm_mon + 1; - - /* read event */ - head = e = ReadEvent(today); - - /* generate calendar */ - buf = AllocCalBuffer(22, 256); - for (i = 0; i < 22; i++) - sprintf(buf[i], "%24s", ""); - for (i = 0; i < 3; i++) { - lines += GenerateCalendar(buf + lines, y, m, today, e) + 1; - if (m == 12) - y++, m = 1; - else - m++; - } - - /* output */ - clear(); - outc('\n'); - for (i = 0; i < 22; i++) { - outs(buf[i]); - if (i == 0) { - prints("\t" ANSI_COLOR(1;37) - "²{¦b¬O %d.%02d.%02d %2d:%02d:%02d%cm" ANSI_RESET, - snow.tm_year + 1900, snow.tm_mon + 1, snow.tm_mday, - (snow.tm_hour == 0 || snow.tm_hour == 12) ? - 12 : snow.tm_hour % 12, snow.tm_min, snow.tm_sec, - snow.tm_hour >= 12 ? 'p' : 'a'); - } else if (i >= 2 && e) { - prints("\t" ANSI_COLOR(1;37) - "(©|¦³ " ANSI_COLOR(%d) "%3d" - ANSI_COLOR(37) " ¤Ñ)" - ANSI_RESET " %02d/%02d %s", - e->color, e->days - today, - e->month, e->day, e->content); - e = e->next; - } - outc('\n'); - } - FreeEvent(head); - FreeCalBuffer(buf); - i = vmsg("½Ð«ö e ½s¿è¦æ¨Æ¾ä¡A©Î¨ä¥¦¥ô·NÁäÂ÷¶}¡C"); - i = tolower(((unsigned char)i) & 0xFF); - if (i == 'e') - { - u_editcalendar(); - } - return 0; -} - diff --git a/mbbsd/card.c b/mbbsd/card.c deleted file mode 100644 index 5f5a1530..00000000 --- a/mbbsd/card.c +++ /dev/null @@ -1,672 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -enum CardSuit { - Spade, Heart, Diamond, Club -}; -static int -card_remain(int cards[]) -{ - int i, temp = 0; - - for (i = 0; i < 52; i++) - temp += cards[i]; - if (temp == 52) - return 1; - return 0; -} - -static enum CardSuit -card_flower(int card) -{ - return (card / 13); -} - -/* 1...13 */ -static int -card_number(int card) -{ - return (card % 13 + 1); -} - -static int -card_isblackjack(int card1, int card2) -{ - return - (card_number(card1)==1 && (10<=card_number(card2) && card_number(card2)<=13)) || - (card_number(card2)==1 && (10<=card_number(card1) && card_number(card1)<=13)); -} - -static int -card_select(int *now) -{ - char *cc[2] = {ANSI_COLOR(44) " " ANSI_RESET, - ANSI_COLOR(1;33;41) " ¡µ " ANSI_RESET}; - - while (1) { - move(20, 0); - clrtoeol(); - prints("%s%s%s%s%s", (*now == 0) ? cc[1] : cc[0], - (*now == 1) ? cc[1] : cc[0], - (*now == 2) ? cc[1] : cc[0], - (*now == 3) ? cc[1] : cc[0], - (*now == 4) ? cc[1] : cc[0]); - switch (igetch()) { - case 'Q': - case 'q': - return 0; - case '+': - case ',': - return 1; - case '\r': - return -1; - case KEY_LEFT: - *now = (*now + 4) % 5; - break; - case KEY_RIGHT: - *now = (*now + 1) % 5; - break; - case '1': - *now = 0; - break; - case '2': - *now = 1; - break; - case '3': - *now = 2; - break; - case '4': - *now = 3; - break; - case '5': - *now = 4; - break; - } - } -} - -static void -card_display(int cline, int number, enum CardSuit flower, int show) -{ - int color = 31; - char *cn[13] = {"¢Ï", "¢±", "¢²", "¢³", "¢´", "¢µ", - "¢¶", "¢·", "¢¸", "10", "¢Ø", "¢ß", "¢Ù"}; - if (flower == 0 || flower == 3) - color = 36; - if ((show < 0) && (cline > 1 && cline < 8)) - outs("¢x" ANSI_COLOR(1;33;42) "¡°¡°¡°¡°" ANSI_RESET "¢x"); - else - switch (cline) { - case 1: - outs("¢~¢w¢w¢w¢w¢¡"); - break; - case 2: - prints("¢x" ANSI_COLOR(1;%d) "%s" ANSI_RESET " ¢x", color, cn[number - 1]); - break; - case 3: - if (flower == 1) - prints("¢x" ANSI_COLOR(1;%d) "¢¨¢©¢¨¢©" ANSI_RESET "¢x", color); - else - prints("¢x" ANSI_COLOR(1;%d) " ¢¨¢© " ANSI_RESET "¢x", color); - break; - case 4: - if (flower == 1) - prints("¢x" ANSI_COLOR(1;%d) "¢i¢i¢i¢i" ANSI_RESET "¢x", color); - else if (flower == 3) - prints("¢x" ANSI_COLOR(1;%d) "¢©¢i¢i¢¨" ANSI_RESET "¢x", color); - else - prints("¢x" ANSI_COLOR(1;%d) "¢¨¢i¢i¢©" ANSI_RESET "¢x", color); - break; - case 5: - if (flower == 0) - prints("¢x" ANSI_COLOR(1;%d) "¢i¢i¢i¢i" ANSI_RESET "¢x", color); - else if (flower == 3) - prints("¢x" ANSI_COLOR(1;%d) "¢i¢ª¢«¢i" ANSI_RESET "¢x", color); - else - prints("¢x" ANSI_COLOR(1;%d) "¢ª¢i¢i¢«" ANSI_RESET "¢x", color); - break; - case 6: - if (flower == 0) - prints("¢x" ANSI_COLOR(1;%d) " ¢¨¢© " ANSI_RESET "¢x", color); - else if (flower == 3) - prints("¢x" ANSI_COLOR(1;%d) "¢ª¢¨¢©¢«" ANSI_RESET "¢x", color); - else - prints("¢x" ANSI_COLOR(1;%d) " ¢ª¢« " ANSI_RESET "¢x", color); - break; - case 7: - prints("¢x " ANSI_COLOR(1;%d) "%s" ANSI_RESET "¢x", color, cn[number - 1]); - break; - case 8: - outs("¢¢¢w¢w¢w¢w¢£"); - break; - } -} - -static void -card_show(int maxncard, int cpu[], int c[], int me[], int m[]) -{ - int i, j; - - for (j = 0; j < 8; j++) { - move(2 + j, 0); - clrtoeol(); - for (i = 0; i < maxncard && cpu[i] >= 0; i++) - card_display(j + 1, card_number(cpu[i]), - card_flower(cpu[i]), c[i]); - } - - for (j = 0; j < 8; j++) { - move(11 + j, 0); - clrtoeol(); - for (i = 0; i < maxncard && me[i] >= 0; i++) - card_display(j + 1, card_number(me[i]), card_flower(me[i]), m[i]); - } -} -static void -card_new(int cards[]) -{ - memset(cards, 0, sizeof(int) * 52); -} - -static int -card_give(int cards[]) -{ - int i; - int freecard[52]; - int nfreecard = 0; - - for(i=0; i<52; i++) - if(cards[i]==0) - freecard[nfreecard++]=i; - - assert(nfreecard>0); /* caller nt³d½T«OÁÙ¦³³ÑµP */ - - i=freecard[random()%nfreecard]; - cards[i] = 1; - return i; -} - -static void -card_start(char name[]) -{ - clear(); - stand_title(name); - move(1, 0); - outs(" " ANSI_COLOR(1;33;41) " ¹q ¸£ " ANSI_RESET); - move(10, 0); - outs(ANSI_COLOR(1;34;44) "¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã" - "¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»¡ã¡»" ANSI_RESET); - move(19, 0); - outs(" " ANSI_COLOR(1;37;42) " ¦Û ¤v " ANSI_RESET); -} - -static int -card_99_add(int i, int aom, int count) -{ - if (i == 4 || i == 5 || i == 11) - return count; - else if (i == 12) - return count + 20 * aom; - else if (i == 10) - return count + 10 * aom; - else if (i == 13) - return 99; - else - return count + i; -} - -static int -card_99_cpu(int cpu[], int *count) -{ - int stop = -1; - int twenty = -1; - int ten = -1; - int kill = -1; - int temp, num[10]; - int other = -1; - int think = 99 - (*count); - int i, j; - - for (i = 0; i < 10; i++) - num[i] = -1; - for (i = 0; i < 5; i++) { - temp = card_number(cpu[i]); - if (temp == 4 || temp == 5 || temp == 11) - stop = i; - else if (temp == 12) - twenty = i; - else if (temp == 10) - ten = i; - else if (temp == 13) - kill = i; - else { - other = i; - num[temp] = i; - } - } - for (j = 9; j > 0; j--) - if (num[j] >= 0 && j != 4 && j != 5 && think >= j) { - (*count) += j; - return num[j]; - } - if ((think >= 20) && (twenty >= 0)) { - (*count) += 20; - return twenty; - } else if ((think >= 10) && (ten >= 0)) { - (*count) += 10; - return ten; - } else if (stop >= 0) - return stop; - else if (kill >= 0) { - (*count) = 99; - return kill; - } else if (ten >= 0) { - (*count) -= 10; - return ten; - } else if (twenty >= 0) { - (*count) -= 20; - return twenty; - } else { - (*count) += card_number(cpu[0]); - return 0; - } -} - -int -card_99(void) -{ - int i, j, turn; - int cpu[5], c[5], me[5], m[5]; - int cards[52]; - int count = 0; - char *ff[4] = {ANSI_COLOR(1;36) "¶Â®ç", ANSI_COLOR(1;31) "¬õ¤ß", - ANSI_COLOR(1;31) "¤è¶ô", ANSI_COLOR(1;36) "¶Âªá"}; - char *cn[13] = {"¢Ï", "¢±", "¢²", "¢³", "¢´", "¢µ", - "¢¶", "¢·", "¢¸", "10", "¢Ø", "¢ß", "¢Ù"}; - for (i = 0; i < 5; i++) - cpu[i] = c[i] = me[i] = m[i] = -1; - setutmpmode(CARD_99); - card_start("¤Ñªø¦a¤["); - card_new(cards); - for (i = 0; i < 5; i++) { - cpu[i] = card_give(cards); - me[i] = card_give(cards); - m[i] = 1; - } - card_show(5, cpu, c, me, m); - j = 0; - turn = 1; - move(21, 0); - clrtoeol(); - prints("[0]¥Ø«e %d , ´Ý %d ÂI\n", count, 99 - count); - outs("¥ª¥kÁä²¾°Ê´å¼Ð, [Enter]½T©w, [ + ]ªí¥[¤G¤Q(¥[¤Q), [Q/q]©ñ±ó¹CÀ¸"); - while (1) { - i = card_select(&j); - if (i == 0) /* ©ñ±ó¹CÀ¸ */ - return 0; - count = card_99_add(card_number(me[j]), i, count); - move(21 + (turn / 2) % 2, 0); - clrtoeol(); - prints("[%d]±z¥X %s%s" ANSI_RESET " ¥Ø«e " ANSI_COLOR(1;31) "%d/" ANSI_COLOR(34) "%d" ANSI_RESET " ÂI", - turn, ff[card_flower(me[j])], - cn[card_number(me[j]) - 1], count, 99 - count); - me[j] = card_give(cards); - turn++; - if (count < 0) - count = 0; - card_show(5, cpu, c, me, m); - pressanykey(); - if (count > 99) { - move(22, 0); - clrtoeol(); - prints("[%d]µ²ªG..YOU LOSS..¥Ø«e " ANSI_COLOR(1;31) "%d/" ANSI_COLOR(34) "%d" ANSI_RESET " ÂI", - turn, count, 99 - count); - pressanykey(); - return 0; - } - i = card_99_cpu(cpu, &count); - move(21 + (turn / 2 + 1) % 2, 40); - prints("[%d]¹q¸£¥X %s%s" ANSI_RESET " ¥Ø«e " ANSI_COLOR(1;31) "%d/" ANSI_COLOR(34) "%d" ANSI_RESET " ÂI", - turn, ff[card_flower(cpu[i])], - cn[card_number(cpu[i]) - 1], count, 99 - count); - cpu[i] = card_give(cards); - turn++; - if (count < 0) - count = 0; - if (count > 99) { - move(22, 0); - clrtoeol(); - prints("[%d]µ²ªG..YOU WIN!..¥Ø«e " ANSI_COLOR(1;31) "%d/" ANSI_COLOR(34) "%d" ANSI_RESET " ÂI", - turn, count, 99 - count); - pressanykey(); - return 0; - } - if (!card_remain(cards)) { - card_new(cards); - for (i = 0; i < 5; i++) { - cards[me[i]] = 1; - cards[cpu[i]] = 1; - } - } - } -} - -#define PMONEY (10) -#define TEN_HALF (5) /* ¤QÂI¥bªºTicket */ -#define JACK (10) /* ¶Â³Ç§JªºTicket */ -#define NINE99 (99) /* 99 ªºTicket */ - -static int -game_log(int type, int money) -{ - FILE *fp; - - if (money > 0) - demoney(money); - - switch (type) { - case JACK: - fp = fopen(BBSHOME "/etc/card/jack.log", "a"); - if (!fp) - return 0; - fprintf(fp, "%s win:%d\n", cuser.userid, money); - fclose(fp); - break; - case TEN_HALF: - fp = fopen(BBSHOME "/etc/card/tenhalf.log", "a"); - if (!fp) - return 0; - fprintf(fp, "%s win:%d\n", cuser.userid, money); - fclose(fp); - break; - } - usleep(100000); // sleep 0.1s - return 0; -} - -static int -card_double_ask(void) -{ - char buf[100], buf2[3]; - - snprintf(buf, sizeof(buf), - "[ %s ]±z²{¦b¦@¦³ %d ¤¸, ²{¦bn¤À²Õ(¥[¦¬ %d ¤¸)¶Ü? [y/N]", - cuser.userid, cuser.money, JACK); - reload_money(); - if (cuser.money < JACK) - return 0; - getdata(20, 0, buf, buf2, sizeof(buf2), LCECHO); - if (buf2[0] == 'y' || buf2[0] == 'Y') - return 1; - return 0; -} - -static int -card_ask(void) -{ - char buf[100], buf2[3]; - - snprintf(buf, sizeof(buf), "[ %s ]±z²{¦b¦@¦³ %d ¤¸, ÁÙn¥[µP¶Ü? [y/N]", - cuser.userid, cuser.money); - getdata(20, 0, buf, buf2, sizeof(buf2), LCECHO); - if (buf2[0] == 'y' || buf2[0] == 'Y') - return 1; - return 0; -} - -static int -card_alls_lower(int all[]) -{ - int i, count = 0; - for (i = 0; i < 6 && all[i] >= 0; i++) - if (card_number(all[i]) <= 10) - count += card_number(all[i]); - else - count += 10; - return count; -} - -static int -card_alls_upper(int all[]) -{ - int i, count; - - count = card_alls_lower(all); - for (i = 0; i < 6 && all[i] >= 0 && count <= 11; i++) - if (card_number(all[i]) == 1) - count += 10; - return count; -} - -static int -card_jack(int *db) -{ - int i, j; - int cpu[6], c[6], me[6], m[6]; - int cards[52]; - - for (i = 0; i < 6; i++) - cpu[i] = c[i] = me[i] = m[i] = -1; - - if ((*db) < 0) { - card_new(cards); - card_start("¶Â³Ç§J"); - for (i = 0; i < 2; i++) { - cpu[i] = card_give(cards); - me[i] = card_give(cards); - } - } else { - card_new(cards); - cards[*db]=1; - card_start("¶Â³Ç§JDOUBLE°l¥[§½"); - cpu[0] = card_give(cards); - cpu[1] = card_give(cards); - me[0] = *db; - me[1] = card_give(cards); - *db = -1; - } - c[1] = m[0] = m[1] = 1; - card_show(6, cpu, c, me, m); - - /* black jack */ - if (card_isblackjack(me[0],me[1])) { - if(card_isblackjack(cpu[0],cpu[1])) { - c[0]=1; - card_show(6, cpu, c, me, m); - game_log(JACK, JACK); - vmsgf("§A¸ò¹q¸£³£®³¨ì¶Â³Ç§J, °hÁÙ %d ¤¸", JACK); - return 0; - } - game_log(JACK, JACK * 5/2); - vmsgf("«Ü¤£¿ùò! (¶Â³Ç§J!! ¥[ %d ¤¸)", JACK * 5/2); - return 0; - } else if(card_isblackjack(cpu[0],cpu[1])) { - c[0] = 1; - card_show(6, cpu, c, me, m); - game_log(JACK, 0); - vmsg("¼K¼K...¤£¦n·N«ä....¶Â³Ç§J!!"); - return 0; - } - - /* double ©îµP */ - if ((card_number(me[0]) == card_number(me[1])) && - (card_double_ask())) { - *db = me[1]; - me[1] = card_give(cards); - card_show(6, cpu, c, me, m); - } - - i = 2; - while (i < 6 && card_ask()) { - me[i] = card_give(cards); - m[i] = 1; - card_show(6, cpu, c, me, m); - if (card_alls_lower(me) > 21) { - game_log(JACK, 0); - vmsg("¶ã¶ã...Ãz±¼¤F!"); - return 0; - } - i++; - } - if (i == 6) { /* µe±¥u¯àÂ\¤»±iµP, ¦]¦¹ª½±µºâª±®aĹ. ¶Â³Ç§J¹ê»Ú¤W¨S³o³W«h */ - game_log(JACK, JACK * 10); - vmsgf("¦n¼F®`ò! ¤»±iµPÁÙ¨SÃz! ¥[ %d ¤¸!", 5 * JACK); - return 0; - } - - j = 2; - c[0] = 1; - while (j<6 && card_alls_upper(cpu)<=16) { - cpu[j] = card_give(cards); - c[j] = 1; - if (card_alls_lower(cpu) > 21) { - card_show(6, cpu, c, me, m); - game_log(JACK, JACK * 2); - vmsgf("¨þ¨þ...¹q¸£Ãz±¼¤F! §AŤF! ¥i±o %d ¤¸", JACK * 2); - return 0; - } - j++; - } - card_show(6, cpu, c, me, m); - if(card_alls_upper(cpu)==card_alls_upper(me)) { - game_log(JACK, JACK); - vmsgf("¥§½¡A°h¦^ %d ¤¸!", JACK); - return 0; - } - if(card_alls_upper(cpu)<card_alls_upper(me)) { - game_log(JACK, JACK * 2); - vmsgf("¨þ¨þ...¹q¸£¤ñ¸û¤p! §AŤF! ¥i±o %d ¤¸", JACK * 2); - return 0; - } - game_log(JACK, 0); - vmsg("«z«z...¹q¸£Ä¹¤F!"); - return 0; -} - -int -g_card_jack(void) -{ - int db; - char buf[3]; - - setutmpmode(JACK_CARD); - while (1) { - reload_money(); - if (cuser.money < JACK) { - outs("±zªº¿ú¤£°÷ò!¥h¦hµoªí¨Ç¦³·N¸qªº¤å³¹¦A¨Ó~~~"); - return 0; - } - getdata(b_lines - 1, 0, "½T©wnª±¶Â³Ç§J¶Ü ¤@¦¸¤Q¤¸ò?(Y/N)?[N]", - buf, 3, LCECHO); - if ((*buf != 'y') && (*buf != 'Y')) - break; - else { - db = -1; - vice(PMONEY, "¶Â³Ç§J"); - do { - card_jack(&db); - } while(db>=0); - } - } - return 0; -} - -static int -card_all(int all[]) -{ - int i, count = 0; - - for (i = 0; i < 5 && all[i] >= 0; i++) - if (card_number(all[i]) <= 10) - count += 2 * card_number(all[i]); - else - count += 1; - return count; -} - -static int -ten_helf(void) -{ - int i, j; - int cpu[5], c[5], me[5], m[5]; - int cards[52]; - - card_start("¤QÂI¥b"); - card_new(cards); - for (i = 0; i < 5; i++) - cpu[i] = c[i] = me[i] = m[i] = -1; - - cpu[0] = card_give(cards); - me[0] = card_give(cards); - m[0] = 1; - card_show(5, cpu, c, me, m); - i = 1; - while (i < 5 && card_ask()) { - me[i] = card_give(cards); - m[i] = 1; - card_show(5, cpu, c, me, m); - if (card_all(me) > 21) { - game_log(TEN_HALF, 0); - vmsg("¶ã¶ã...Ãz±¼¤F!"); - return 0; - } - i++; - } - if (i == 5) { /* ¹L¤Ãö */ - game_log(TEN_HALF, PMONEY * 5); - vmsgf("¦n¼F®`ò! ¹L¤Ãö¹Æ! ¥[ %d ¤¸!", 5 * PMONEY); - return 0; - } - j = 1; - c[0] = 1; - while (j < 5 && ((card_all(cpu) < card_all(me)) || - (card_all(cpu) == card_all(me) && j < i))) { - cpu[j] = card_give(cards); - c[j] = 1; - if (card_all(cpu) > 21) { - card_show(5, cpu, c, me, m); - game_log(TEN_HALF, PMONEY * 2); - vmsgf("¨þ¨þ...¹q¸£Ãz±¼¤F! §AŤF! ¥i±o %d ¤¸", PMONEY * 2); - return 0; - } - j++; - } - card_show(5, cpu, c, me, m); - game_log(TEN_HALF, 0); - vmsg("«z«z...¹q¸£Ä¹¤F!"); - return 0; -} - -int -g_ten_helf(void) -{ - char buf[3]; - int times = 0; - - setutmpmode(TENHALF); - while (1) { - reload_money(); - if (cuser.money < TEN_HALF) { - outs("±zªº¿ú¤£°÷ò!¥h¦hµoªí¨Ç¦³·N¸qªº¤å³¹¦A¨Ó~~~"); - return 0; - } - - if (times++ % 5 == 0) - { - move(b_lines-2, 0); clrtoeol(); - outs(ANSI_COLOR(1;31) - "ĵ§i: ¥»¹CÀ¸¥Ñ PttGames ¬ÝªOµûŲ¬°·¥«×¶Â©±¡A½Ð¤p¤ß¡I" ANSI_RESET); - } - - getdata(b_lines - 1, 0, - ANSI_COLOR(1;37) "½T©wnª±¤QÂI¥b¶Ü ¤@¦¸¤Q¤¸ò?(Y/N)?[N]" ANSI_RESET, - buf, 3, LCECHO); - if (buf[0] != 'y' && buf[0] != 'Y') - return 0; - else { - vice(PMONEY, "¤QÂI¥b"); - ten_helf(); - } - } - return 0; -} diff --git a/mbbsd/chat.c b/mbbsd/chat.c deleted file mode 100644 index 6623fbc2..00000000 --- a/mbbsd/chat.c +++ /dev/null @@ -1,597 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#ifndef DBCSAWARE -#define dbcs_off (1) -#endif - -#define STOP_LINE (t_lines-3) -static int chatline; -static FILE *flog; -static void -printchatline(const char *str) -{ - move(chatline, 0); - if (*str == '>' && !PERM_HIDE(currutmp)) - return; - else if (chatline < STOP_LINE - 1) - chatline++; - else { - region_scroll_up(2, STOP_LINE - 2); - move(STOP_LINE - 2, 0); - } - outs(str); - outc('\n'); - outs("¡÷"); - - if (flog) - fprintf(flog, "%s\n", str); -} - -static void -chat_clear(char*unused) -{ - for (chatline = 2; chatline < STOP_LINE; chatline++) { - move(chatline, 0); - clrtoeol(); - } - move(b_lines, 0); - clrtoeol(); - move(chatline = 2, 0); - outs("¡÷"); -} - -static void -print_chatid(const char *chatid) -{ - move(b_lines - 1, 0); - clrtoeol(); - outs(chatid); - outc(':'); -} - -static int -chat_send(int fd, const char *buf) -{ - int len; - char genbuf[200]; - - len = snprintf(genbuf, sizeof(genbuf), "%s\n", buf); - return (send(fd, genbuf, len, 0) == len); -} - -struct ChatBuf { - char buf[128]; - int bufstart; -}; - -static int -chat_recv(struct ChatBuf *cb, int fd, char *chatroom, char *chatid, size_t chatid_size) -{ - int c, len; - char *bptr; - - len = sizeof(cb->buf) - cb->bufstart - 1; - if ((c = recv(fd, cb->buf + cb->bufstart, len, 0)) <= 0) - return -1; - c += cb->bufstart; - - bptr = cb->buf; - while (c > 0) { - len = strlen(bptr) + 1; - if (len > c && (unsigned)len < (sizeof(cb->buf)/ 2) ) - break; - - if (*bptr == '/') { - switch (bptr[1]) { - case 'c': - chat_clear(NULL); - break; - case 'n': - strlcpy(chatid, bptr + 2, chatid_size); - print_chatid(chatid); - clrtoeol(); - break; - case 'r': - strlcpy(chatroom, bptr + 2, IDLEN); - break; - case 't': - move(0, 0); - clrtoeol(); - prints(ANSI_COLOR(1;37;46) " ½Í¤Ñ«Ç [%-12s] " ANSI_COLOR(45) " ¸ÜÃD¡G%-48s" ANSI_RESET, - chatroom, bptr + 2); - } - } else - printchatline(bptr); - - c -= len; - bptr += len; - } - - if (c > 0) { - memmove(cb->buf, bptr, sizeof(cb->buf)-(bptr-cb->buf)); - cb->bufstart = len - 1; - } else - cb->bufstart = 0; - return 0; -} - -static void -chathelp(const char *cmd, const char *desc) -{ - char buf[STRLEN]; - - snprintf(buf, sizeof(buf), " %-20s- %s", cmd, desc); - printchatline(buf); -} - -static void -chat_help(char *arg) -{ - if (strstr(arg, " op")) { - printchatline("½Í¤Ñ«ÇºÞ²zû±M¥Î«ü¥O"); - chathelp("[/f]lag [+-][ls]", "³]©wÂê©w¡B¯µ±Kª¬ºA"); - chathelp("[/i]nvite <id>", "ÁܽР<id> ¥[¤J½Í¤Ñ«Ç"); - chathelp("[/k]ick <id>", "±N <id> ½ð¥X½Í¤Ñ«Ç"); - chathelp("[/o]p <id>", "±N Op ªºÅv¤OÂಾµ¹ <id>"); - chathelp("[/t]opic <text>", "´«Ó¸ÜÃD"); - chathelp("[/w]all", "¼s¼½ (¯¸ªø±M¥Î)"); - } else { - // chathelp("[/.]help", "chicken °«Âû¥Î«ü¥O"); - chathelp(" /help op", "½Í¤Ñ«ÇºÞ²zû±M¥Î«ü¥O"); - chathelp("[//]help", "MUD-like ªÀ¥æ°Êµü"); - chathelp("[/a]ct <msg>", "°µ¤@Ӱʧ@"); - chathelp("[/b]ye [msg]", "¹D§O"); - chathelp("[/c]lear", "²M°£¿Ã¹õ"); - chathelp("[/j]oin <room>", "«Ø¥ß©Î¥[¤J½Í¤Ñ«Ç"); - chathelp("[/l]ist [room]", "¦C¥X½Í¤Ñ«Ç¨Ï¥ÎªÌ"); - chathelp("[/m]sg <id> <msg>", "¸ò <id> »¡®¨®¨¸Ü"); - chathelp("[/n]ick <id>", "±N½Í¤Ñ¥N¸¹´«¦¨ <id>"); - chathelp("[/p]ager", "¤Á´«©I¥s¾¹"); - chathelp("[/q]uery <id>", "¬d¸ßºô¤Í"); - chathelp("[/r]oom ", "¦C¥X¤@¯ë½Í¤Ñ«Ç"); - chathelp("[/w]ho", "¦C¥X¥»½Í¤Ñ«Ç¨Ï¥ÎªÌ"); - chathelp(" /whoin <room>", "¦C¥X½Í¤Ñ«Ç<room> ªº¨Ï¥ÎªÌ"); - chathelp(" /ignore <userid>", "©¿²¤«ü©w¨Ï¥ÎªÌªº°T®§"); - chathelp(" /unignore <userid>", "°±¤î©¿²¤«ü©w¨Ï¥ÎªÌªº°T®§"); - } -} - -static void -chat_date(char *unused) -{ - char genbuf[200]; - - snprintf(genbuf, sizeof(genbuf), - "¡» " BBSNAME "¼Ð·Ç®É¶¡: %s", Cdate(&now)); - printchatline(genbuf); -} - -static void -chat_pager(char *unused) -{ - char genbuf[200]; - - char *msgs[PAGER_MODES] = { - /* Ref: please match PAGER* in modes.h */ - "Ãö³¬", "¥´¶}", "©Þ±¼", "¨¾¤ô", "¦n¤Í" - }; - - snprintf(genbuf, sizeof(genbuf), "¡» ±zªº©I¥s¾¹:[%s]", - msgs[currutmp->pager = (currutmp->pager + 1) % PAGER_MODES]); - printchatline(genbuf); -} - -static void -chat_query(char *arg) -{ - char *uid; - int tuid; - userec_t xuser; - char *strtok_pos; - - printchatline(""); - strtok_r(arg, str_space, &strtok_pos); - if ((uid = strtok_r(NULL, str_space, &strtok_pos)) && (tuid = getuser(uid, &xuser))) { - char buf[128], *ptr; - FILE *fp; - - snprintf(buf, sizeof(buf), "%s(%s) ¦@¤W¯¸ %d ¦¸¡Aµoªí¹L %d ½g¤å³¹", - xuser.userid, xuser.nickname, - xuser.numlogins, xuser.numposts); - printchatline(buf); - - snprintf(buf, sizeof(buf), - "³Ìªñ(%s)±q[%s]¤W¯¸", Cdate(&xuser.lastlogin), - (xuser.lasthost[0] ? xuser.lasthost : "(¤£¸Ô)")); - printchatline(buf); - - sethomefile(buf, xuser.userid, fn_plans); - if ((fp = fopen(buf, "r"))) { - tuid = 0; - while (tuid++ < MAX_QUERYLINES && fgets(buf, 128, fp)) { - if ((ptr = strchr(buf, '\n'))) - ptr[0] = '\0'; - printchatline(buf); - } - fclose(fp); - } - } else - printchatline(err_uid); -} - -typedef struct chat_command_t { - char *cmdname; /* Chatroom command length */ - void (*cmdfunc) (char *); /* Pointer to function */ -} chat_command_t; - -static const chat_command_t chat_cmdtbl[] = { - {"help", chat_help}, - {"clear", chat_clear}, - {"date", chat_date}, - {"pager", chat_pager}, - {"query", chat_query}, - {NULL, NULL} -}; - -static int -chat_cmd_match(const char *buf, const char *str) -{ - while (*str && *buf && !isspace((int)*buf)) - if (tolower(*buf++) != *str++) - return 0; - return 1; -} - -static int -chat_cmd(char *buf, int fd) -{ - int i; - - if (*buf++ != '/') - return 0; - - for (i = 0; chat_cmdtbl[i].cmdname; i++) { - if (chat_cmd_match(buf, chat_cmdtbl[i].cmdname)) { - chat_cmdtbl[i].cmdfunc(buf); - return 1; - } - } - return 0; -} - -#define MAXLASTCMD 6 -static int chatid_len = 10; -static time4_t lastEnter = 0; - -int -t_chat(void) -{ - char chatroom[IDLEN];/* Chat-Room Name */ - char inbuf[80], chatid[20], lastcmd[MAXLASTCMD][80], *ptr = ""; - struct sockaddr_in sin; - int cfd, cmdpos, ch; - int currchar; - int chatting = YEA; - char fpath[80]; - struct ChatBuf chatbuf; - - if(HasUserPerm(PERM_VIOLATELAW)) - { - vmsg("½Ð¥ýú»@³æ¤~¯à¨Ï¥Î²á¤Ñ«Ç!"); - return -1; - } - - syncnow(); - -#ifdef CHAT_GAPMINS - if ((now - lastEnter)/60 < CHAT_GAPMINS) - { - vmsg("±z¤~èÂ÷¶}²á¤Ñ«Ç¡A¸Ì±¥¿¦b¾ã²z¤¤¡C½Ðµy«á¦A¸Õ¡C"); - return 0; - } -#endif - -#ifdef CHAT_REGDAYS - if ((now - cuser.firstlogin)/86400 < CHAT_REGDAYS) - { - int i = CHAT_REGDAYS - (now-cuser.firstlogin)/86400 +1; - vmsgf("±zÁÙ¤£°÷¸ê²`³á (¦Aµ¥ %d ¤Ñ§a)", i); - return 0; - } -#endif - - memset(&chatbuf, 0, sizeof(chatbuf)); - outs(" ÅX¨®«e©¹ ½Ð±éÔ........ "); - - memset(&sin, 0, sizeof sin); -#ifdef __FreeBSD__ - sin.sin_len = sizeof(sin); -#endif - sin.sin_family = PF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(NEW_CHATPORT); - cfd = socket(sin.sin_family, SOCK_STREAM, 0); - if (connect(cfd, (struct sockaddr *) & sin, sizeof sin) != 0) { - outs("\n " - "«z! ¨S¤H¦b¨ºÃäC...n¦³¨º¦a¤èªº¤H¥ý¥h¶}ªù°Õ!..."); - system("bin/xchatd"); - pressanykey(); - close(cfd); - return -1; - } - - while (1) { - getdata(b_lines - 1, 0, "½Ð¿é¤J²á¤Ñ¥N¸¹¡G", chatid, 9, DOECHO); - if(!chatid[0]) - strlcpy(chatid, cuser.userid, sizeof(chatid)); - chatid[8] = '\0'; - /* - * ·s®æ¦¡: /! UserID ChatID Password - */ - snprintf(inbuf, sizeof(inbuf), "/! %s %s %s", - cuser.userid, chatid, cuser.passwd); - chat_send(cfd, inbuf); - if (recv(cfd, inbuf, 3, 0) != 3) { - close(cfd); - vmsg("¨t²Î¿ù»~¡C"); - return 0; - } - if (!strcmp(inbuf, CHAT_LOGIN_OK)) - break; - else if (!strcmp(inbuf, CHAT_LOGIN_EXISTS)) - ptr = "³oÓ¥N¸¹¤w¸g¦³¤H¥Î¤F"; - else if (!strcmp(inbuf, CHAT_LOGIN_INVALID)) - ptr = "³oÓ¥N¸¹¬O¿ù»~ªº"; - else if (!strcmp(inbuf, CHAT_LOGIN_BOGUS)) - ptr = "½Ð¤Å¬£»º¤À¨¶i¤J²á¤Ñ«Ç !!"; - - move(b_lines - 2, 0); - outs(ptr); - clrtoeol(); - bell(); - } - syncnow(); - lastEnter = now; - - add_io(cfd, 0); - - currchar = 0; - cmdpos = -1; - memset(lastcmd, 0, sizeof(lastcmd)); - - setutmpmode(CHATING); - currutmp->in_chat = YEA; - strlcpy(currutmp->chatid, chatid, sizeof(currutmp->chatid)); - - clear(); - chatline = 2; - - move(STOP_LINE, 0); - outs(msg_seperator); - move(STOP_LINE, 56); - outs(" /h ¬d¸ß«ü¥O /b Â÷¶} "); - move(1, 0); - outs(msg_seperator); - print_chatid(chatid); - memset(inbuf, 0, sizeof(inbuf)); - - setuserfile(fpath, "chat_XXXXXX"); - flog = fdopen(mkstemp(fpath), "w"); - - while (chatting) { - move(b_lines - 1, currchar + chatid_len); - ch = igetch(); - - switch (ch) { - case KEY_DOWN: - cmdpos += MAXLASTCMD - 2; - case KEY_UP: - cmdpos++; - cmdpos %= MAXLASTCMD; - strlcpy(inbuf, lastcmd[cmdpos], sizeof(inbuf)); - move(b_lines - 1, chatid_len); - clrtoeol(); - outs(inbuf); - currchar = strlen(inbuf); - continue; - case KEY_LEFT: - if (currchar) - { - --currchar; -#ifdef DBCSAWARE - if(currchar > 0 && - ISDBCSAWARE() && - getDBCSstatus((unsigned char*)inbuf, currchar) == DBCS_TRAILING) - currchar --; -#endif - } - continue; - case KEY_RIGHT: - if (inbuf[currchar]) - { - ++currchar; -#ifdef DBCSAWARE - if(inbuf[currchar] && - ISDBCSAWARE() && - getDBCSstatus((unsigned char*)inbuf, currchar) == DBCS_TRAILING) - currchar++; -#endif - } - continue; - case KEY_UNKNOWN: - continue; - } - - if (ISNEWMAIL(currutmp)) { - printchatline("¡» ¾´¡I¶l®t¤S¨Ó¤F..."); - } - if (ch == I_OTHERDATA) {/* incoming */ - if (chat_recv(&chatbuf, cfd, chatroom, chatid, 9) == -1) { - chatting = chat_send(cfd, "/b"); - break; - } - } else if (isprint2(ch)) { - if (currchar < 68) { - if (inbuf[currchar]) { /* insert */ - int i; - - for (i = currchar; inbuf[i] && i < 68; i++); - inbuf[i + 1] = '\0'; - for (; i > currchar; i--) - inbuf[i] = inbuf[i - 1]; - } else /* append */ - inbuf[currchar + 1] = '\0'; - inbuf[currchar] = ch; - move(b_lines - 1, currchar + chatid_len); - outs(&inbuf[currchar++]); - } - } else if (ch == '\n' || ch == '\r') { - if (*inbuf) { - -#ifdef EXP_ANTIFLOOD - // prevent flooding */ - static time4_t lasttime = 0; - static int flood = 0; - - /* // debug anti flodding - move(b_lines-3, 0); clrtoeol(); - prints("lasttime=%d, now=%d, flood=%d\n", - lasttime, now, flood); - refresh(); - */ - syncnow(); - if (now - lasttime < 3 ) - { - // 3 ¬í¤º¬~¥b±¬O¤£¦æªº ((25-5)/2) - if( ++flood > 10 ){ - // flush all input! - drop_input(); - while (wait_input(1, 0)) - { - if (num_in_buf()) - drop_input(); - else - tty_read((unsigned char*)inbuf, sizeof(inbuf)); - } - drop_input(); - vmsg("½Ð¤Å¤j¶q°Å¶K©Î³y¦¨¬~ªO±ªº®ÄªG¡C"); - // log? - sleep(2); - continue; - } - } else { - lasttime = now; - flood = 0; - } -#endif // anti-flood - - chatting = chat_cmd(inbuf, cfd); - if (chatting == 0) - chatting = chat_send(cfd, inbuf); - if (!strncmp(inbuf, "/b", 2)) - break; - - for (cmdpos = MAXLASTCMD - 1; cmdpos; cmdpos--) - strlcpy(lastcmd[cmdpos], - lastcmd[cmdpos - 1], sizeof(lastcmd[cmdpos])); - strlcpy(lastcmd[0], inbuf, sizeof(lastcmd[0])); - - inbuf[0] = '\0'; - currchar = 0; - cmdpos = -1; - } - print_chatid(chatid); - move(b_lines - 1, chatid_len); - } else if (ch == Ctrl('H') || ch == '\177') { - if (currchar) { -#ifdef DBCSAWARE - int dbcs_off = 1; - if (ISDBCSAWARE() && - getDBCSstatus((unsigned char*)inbuf, currchar-1) == DBCS_TRAILING) - dbcs_off = 2; -#endif - currchar -= dbcs_off; - inbuf[69] = '\0'; - memcpy(&inbuf[currchar], &inbuf[currchar + dbcs_off], - 69 - currchar); - move(b_lines - 1, currchar + chatid_len); - clrtoeol(); - outs(&inbuf[currchar]); - } - } else if (ch == Ctrl('Z') || ch == Ctrl('Y')) { - inbuf[0] = '\0'; - currchar = 0; - print_chatid(chatid); - move(b_lines - 1, chatid_len); - } else if (ch == Ctrl('C')) { - chat_send(cfd, "/b"); - break; - } else if (ch == Ctrl('D')) { - if ((size_t)currchar < strlen(inbuf)) { -#ifdef DBCSAWARE - int dbcs_off = 1; - if (ISDBCSAWARE() && inbuf[currchar+1] && - getDBCSstatus((unsigned char*)inbuf, currchar+1) == DBCS_TRAILING) - dbcs_off = 2; -#endif - inbuf[69] = '\0'; - memcpy(&inbuf[currchar], &inbuf[currchar + dbcs_off], - 69 - currchar); - move(b_lines - 1, currchar + chatid_len); - clrtoeol(); - outs(&inbuf[currchar]); - } - } else if (ch == Ctrl('K')) { - inbuf[currchar] = 0; - move(b_lines - 1, currchar + chatid_len); - clrtoeol(); - } else if (ch == Ctrl('A')) { - currchar = 0; - } else if (ch == Ctrl('E')) { - currchar = strlen(inbuf); - } else if (ch == Ctrl('I')) { - screen_backup_t old_screen; - - scr_dump(&old_screen); - add_io(0, 0); - t_idle(); - scr_restore(&old_screen); - add_io(cfd, 0); - } else if (ch == Ctrl('Q')) { - print_chatid(chatid); - move(b_lines - 1, chatid_len); - outs(inbuf); - continue; - } - } - - close(cfd); - add_io(0, 0); - currutmp->in_chat = currutmp->chatid[0] = 0; - - if (flog) { - char ans[4]; - - fclose(flog); - more(fpath, NA); - getdata(b_lines - 1, 0, "²M°£(C) ²¾¦Ü³Æ§Ñ¿ý(M) (C/M)?[C]", - ans, sizeof(ans), LCECHO); - if (*ans == 'm') { - fileheader_t mymail; - char title[128]; - char genbuf[200]; - - sethomepath(genbuf, cuser.userid); - stampfile(genbuf, &mymail); - mymail.filemode = FILE_READ ; - strlcpy(mymail.owner, "[³Æ.§Ñ.¿ý]", sizeof(mymail.owner)); - strlcpy(mymail.title, "·|ij" ANSI_COLOR(1;33) "°O¿ý" ANSI_RESET, sizeof(mymail.title)); - sethomedir(title, cuser.userid); - append_record(title, &mymail, sizeof(mymail)); - Rename(fpath, genbuf); - } else - unlink(fpath); - } - return 0; -} diff --git a/mbbsd/chc.c b/mbbsd/chc.c deleted file mode 100644 index 602fc37e..00000000 --- a/mbbsd/chc.c +++ /dev/null @@ -1,1012 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -#include "chc.h" - -#define assert_not_reached() assert(!"Should never be here!!!") - -extern const double elo_exp_tab[1000]; - -enum Turn { - BLK = 0, - RED -}; - -enum Kind { - KIND_K=1, - KIND_A, - KIND_E, - KIND_R, - KIND_H, - KIND_C, - KIND_P, -}; -#define CENTER(a, b) (((a) + (b)) >> 1) -#define CHC_TIMEOUT 300 - -#define PHOTO_LINE 15 -#define PHOTO_COLUMN (256 + 25) - -typedef struct drc_t { - ChessStepType type; /* necessary one */ - rc_t from, to; -} drc_t; - -typedef struct { - rc_t select; - char selected; -} chc_tag_data_t; - -/* chess framework action functions */ -static void chc_init_user(const userinfo_t *uinfo, ChessUser *user); -static void chc_init_user_userec(const userec_t *urec, ChessUser *user); -static void chc_init_board(board_t board); -static void chc_drawline(const ChessInfo* info, int line); -static void chc_movecur(int r, int c); -static int chc_prepare_play(ChessInfo* info); -static int chc_select(ChessInfo* info, rc_t scrloc, ChessGameResult* result); -static void chc_prepare_step(ChessInfo* info, const void* step); -static ChessGameResult chc_movechess(board_t board, const drc_t* move); -static void chc_drawstep(ChessInfo* info, const drc_t* move); -static void chc_gameend(ChessInfo* info, ChessGameResult result); -static void chc_genlog(ChessInfo* info, FILE* fp, ChessGameResult result); - - -static const char * const turn_color[2]={BLACK_COLOR, RED_COLOR}; - -/* some constant variable definition */ - -static const char * const turn_str[2] = {"¶Âªº", "¬õªº"}; - -static const char * const num_str[2][10] = { - {"", "¢°", "¢±", "¢²", "¢³", "¢´", "¢µ", "¢¶", "¢·", "¢¸"}, - {"", "¤@", "¤G", "¤T", "¥|", "¤", "¤»", "¤C", "¤K", "¤E"}, -}; - -static const char * const chess_str[2][8] = { - /* 0 1 2 3 4 5 6 7 */ - {" ", "±N", "¤h", "¶H", "¨®", "°¨", "¥]", "¨ò"}, - {" ", "«Ó", "¥K", "¬Û", "¨®", "ØX", "¬¶", "§L"} -}; - -static const char * const chess_brd[BRD_ROW * 2 - 1] = { - /* 0 1 2 3 4 5 6 7 8 */ - "¢z¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢{", /* 0 */ - "¢x ¢x ¢x ¢x¢@¢x¡þ¢x ¢x ¢x ¢x", - "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 1 */ - "¢x ¢x ¢x ¢x¡þ¢x¢@¢x ¢x ¢x ¢x", - "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 2 */ - "¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x", - "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 3 */ - "¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x", - "¢u¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢t", /* 4 */ - "¢x ·¡ ªe º~ ¬É ¢x", - "¢u¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢t", /* 5 */ - "¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x", - "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 6 */ - "¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x", - "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 7 */ - "¢x ¢x ¢x ¢x¢@¢x¡þ¢x ¢x ¢x ¢x", - "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t", /* 8 */ - "¢x ¢x ¢x ¢x¡þ¢x¢@¢x ¢x ¢x ¢x", - "¢|¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢}" /* 9 */ -}; - -static char * const hint_str[] = { - " q »{¿éÂ÷¶}", - " p n¨D©M´Ñ", - "¤è¦VÁä ²¾°Ê¹C¼Ð", - "Enter ¿ï¾Ü/²¾°Ê" -}; - -static const ChessActions chc_actions = { - &chc_init_user, - &chc_init_user_userec, - (void (*) (void*)) &chc_init_board, - &chc_drawline, - &chc_movecur, - &chc_prepare_play, - NULL, /* process_key */ - &chc_select, - &chc_prepare_step, - (ChessGameResult (*) (void*, const void*)) &chc_movechess, - (void (*)(ChessInfo*, const void*)) &chc_drawstep, - NULL, /* post_game */ - &chc_gameend, - &chc_genlog -}; - -static const ChessConstants chc_constants = { - sizeof(drc_t), - CHC_TIMEOUT, - BRD_ROW, - BRD_COL, - 0, - "·¡ªeº~¬É", - "photo_cchess", -#ifdef GLOBAL_CCHESS_LOG - GLOBAL_CCHESS_LOG, -#else - NULL, -#endif - { BLACK_COLOR, RED_COLOR }, - {"¶Âªº", "¬õªº"} -}; - -/* - * Start of the drawing function. - */ -static void -chc_movecur(int r, int c) -{ - move(r * 2 + 3, c * 4 + 4); -} - -static char * -getstep(board_t board, const rc_t *from, const rc_t *to, char buf[]) -{ - int turn, fc, tc; - char *dir; - int twin = 0, twin_r = 0; - int len = 0; - - turn = CHE_O(board[from->r][from->c]); - if(CHE_P(board[from->r][from->c] != KIND_P)) { // TODO ¥Ø«e¤£ºÞ§L¨ò«e«á - int i; - for(i=0;i<10;i++) - if(board[i][from->c]==board[from->r][from->c]) { - if(i!=from->r) { - twin=1; - twin_r=i; - } - } - } - fc = (turn == BLK ? from->c + 1 : 9 - from->c); - tc = (turn == BLK ? to->c + 1 : 9 - to->c); - if (from->r == to->r) - dir = "¥"; - else { - if (from->c == to->c) - tc = from->r - to->r; - if (tc < 0) - tc = -tc; - - if ((turn == BLK && to->r > from->r) || - (turn == RED && to->r < from->r)) - dir = "¶i"; - else - dir = "°h"; - } - - - len=sprintf(buf, "%s", turn_color[turn]); - /* ØX¤G|«eØX */ - if(twin) { - len+=sprintf(buf+len, "%s%s", - ((from->r>twin_r)==(turn==(BLK)))?"«e":"«á", - chess_str[turn][CHE_P(board[from->r][from->c])]); - } else { - len+=sprintf(buf+len, "%s%s", - chess_str[turn][CHE_P(board[from->r][from->c])], - num_str[turn][fc]); - } - /* ¶i¤T */ - len+=sprintf(buf+len, "%s%s" ANSI_RESET, dir, num_str[turn][tc]); - /* ¡G¶H */ - if(board[to->r][to->c]) { - len+=sprintf(buf+len,"¡G%s%s" ANSI_RESET, - turn_color[turn^1], - chess_str[turn^1][CHE_P(board[to->r][to->c])]); - } - return buf; -} - -inline static const char* -chc_timestr(int second) -{ - static char str[10]; - snprintf(str, sizeof(str), "%d:%02d", second / 60, second % 60); - return str; -} - -static void -chc_drawline(const ChessInfo* info, int line) -{ - int i, j; - board_p board = (board_p) info->board; - chc_tag_data_t *tag = info->tag; - - if (line == 0) { - prints(ANSI_COLOR(1;46) " ¶H´Ñ¹ï¾Ô " ANSI_COLOR(45) - "%30s VS %-20s%10s" ANSI_RESET, - info->user1.userid, info->user2.userid, - info->mode == CHESS_MODE_WATCH ? "[Æ[´Ñ¼Ò¦¡]" : ""); - } else if (line >= 3 && line <= 21) { - outs(" "); - for (i = 0; i < 9; i++) { - j = board[RTL(info,line)][CTL(info,i)]; - if ((line & 1) == 1 && j) { - if (tag->selected && - tag->select.r == RTL(info,line) && tag->select.c == CTL(info,i)) { - prints("%s%s" ANSI_RESET, - CHE_O(j) == BLK ? BLACK_REVERSE : RED_REVERSE, - chess_str[CHE_O(j)][CHE_P(j)]); - } - else { - prints("%s%s" ANSI_RESET, - turn_color[CHE_O(j)], - chess_str[CHE_O(j)][CHE_P(j)]); - } - } else - prints("%c%c", chess_brd[line - 3][i * 4], - chess_brd[line - 3][i * 4 + 1]); - if (i != 8) - prints("%c%c", chess_brd[line - 3][i * 4 + 2], - chess_brd[line - 3][i * 4 + 3]); - } - } else if (line == 2 || line == 22) { - outs(" "); - if (line == 2) - for (i = 1; i <= 9; i++) - prints("%s ", num_str[REDDOWN(info)?0:1][i]); - else - for (i = 9; i >= 1; i--) - prints("%s ", num_str[REDDOWN(info)?1:0][i]); - } - - ChessDrawExtraInfo(info, line, 8); -} -/* - * End of the drawing function. - */ - - -/* - * Start of the log function. - */ - -static void -chc_log_machine_step(FILE* fp, board_t board, const drc_t *step) -{ - const static char chess_char[8] = { - 0, 'K', 'A', 'B', 'R', 'N', 'C', 'P' - }; - /* We have black at bottom in rc_t but the standard is - * the red side at bottom, so that a rotation is needed. */ - fprintf(fp, "%c%c%d%c%c%d ", - chess_char[CHE_P(board[step->from.r][step->from.c])], - step->from.c + 'a', BRD_ROW - step->from.r - 1, - board[step->to.r][step->to.c] ? 'x' : '-', - step->to.c + 'a', BRD_ROW - step->to.r - 1 - ); -} - -static int -#if defined(__linux__) -chc_filter(const struct dirent *dir) -#else -chc_filter(struct dirent *dir) -#endif -{ - if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0 ) - return 0; - return strstr(dir->d_name, ".poem") != NULL; -} - -static int -chc_log_poem(FILE* outfp) -{ - struct dirent **namelist; - int n; - - // TODO use readdir(), don't use lots of memory - n = scandir(BBSHOME"/etc/chess", &namelist, chc_filter, alphasort); - if (n < 0) - perror("scandir"); - else { - char buf[80]; - FILE *fp; - sprintf(buf, BBSHOME"/etc/chess/%s", namelist[random() % n]->d_name); - if ((fp = fopen(buf, "r")) == NULL) - return -1; - - while(fgets(buf, sizeof(buf), fp) != NULL) - fputs(buf, outfp); - while(n--) - free(namelist[n]); - free(namelist); - fclose(fp); - } - return 0; -} - -static void -chc_genlog(ChessInfo* info, FILE* fp, ChessGameResult result) -{ - const int nStep = info->history.used; - board_t board; - int i; - - fprintf(fp, "«ö z ¥i¶i¤J¥´ÃмҦ¡\n"); - fprintf(fp, "\n"); - - if (info->myturn == RED) - fprintf(fp, "%s(%d) V.S. %s(%d)\n", - info->user1.userid, info->user1.orig_rating, - info->user2.userid, info->user2.orig_rating); - else - fprintf(fp, "%s(%d) V.S. %s(%d)\n", - info->user2.userid, info->user2.orig_rating, - info->user1.userid, info->user1.orig_rating); - - chc_init_board(board); - /* format: "%3d. %8.8s %8.8s %3d. %8.8s %8.8s\n" */ - for (i = 0; i < nStep; i++) { - char buf[80]; - const drc_t *move = (const drc_t*) ChessHistoryRetrieve(info, i); - buf[0]='\0'; - if (move->type == CHESS_STEP_NORMAL) { - getstep(board, &move->from, &move->to, buf); - chc_movechess(board, move); - if(i%2==0) fprintf(fp, "%3d. ",i/2+1); - strip_ansi(buf, buf, STRIP_ALL); - fprintf(fp, "%8.8s ", buf); - if(i%4==3 || i==nStep-1) fputc('\n', fp); - } - } - - if (result == CHESS_RESULT_TIE) - fprintf(fp, "=> ©M§½\n"); - else if (result == CHESS_RESULT_WIN || result == CHESS_RESULT_LOST) - fprintf(fp, "=> %s ³Ó\n", - (info->myturn == RED) == (result== CHESS_RESULT_WIN) ? - "¬õ" : "¶Â"); - - /* generate machine readable log. - * http://www.elephantbase.net/protocol/cchess_pgn.htm */ - { - /* machine readable header */ - time_t temp = (time_t) now; - struct tm *mytm = localtime(&temp); - - fprintf(fp, - "\n\n<chclog>\n" - "[Game \"Chinese Chess\"]\n" - "[Date \"%d.%d.%d\"]\n" - "[Red \"%s\"]\n" - "[Black \"%s\"]\n", - mytm->tm_year + 1900, mytm->tm_mon + 1, mytm->tm_mday, - info->myturn == RED ? info->user1.userid : info->user2.userid, - info->myturn == RED ? info->user2.userid : info->user1.userid - ); - - if (result == CHESS_RESULT_TIE || result == CHESS_RESULT_WIN || - result == CHESS_RESULT_LOST) - fprintf(fp, "[Result \"%s\"]\n", - result == CHESS_RESULT_TIE ? "0.5-0.5" : - (info->myturn == RED) == (result== CHESS_RESULT_WIN) ? - "1-0" : "0-1"); - else - fprintf(fp, "[Result \"*\"]\n"); - - fprintf(fp, - "[Notation \"Coord\"]\n" - "[FEN \"rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR" - " r - - 0 1\"]\n"); - } - chc_init_board(board); - for (i = 0; i < nStep - 1; i += 2) { - const drc_t *move = (const drc_t*) ChessHistoryRetrieve(info, i); - fprintf(fp, "%2d. ", i / 2 + 1); - if (move->type == CHESS_STEP_NORMAL) { - chc_log_machine_step(fp, board, move); - chc_movechess(board, move); - } - - fputs(" ", fp); - - move = (const drc_t*) ChessHistoryRetrieve(info, i + 1); - if (move->type == CHESS_STEP_NORMAL) { - chc_log_machine_step(fp, board, move); - chc_movechess(board, move); - } - - fputc('\n', fp); - } - if (i < nStep) { - const drc_t *move = (const drc_t*) ChessHistoryRetrieve(info, i); - if (move->type == CHESS_STEP_NORMAL) { - fprintf(fp, "%2d. ", i / 2 + 1); - chc_log_machine_step(fp, board, move); - fputc('\n', fp); - } - } - - fputs("</chclog>\n\n--\n\n", fp); - chc_log_poem(fp); -} -/* - * End of the log function. - */ - - -/* - * Start of the rule function. - */ -static void -chc_init_board(board_t board) -{ - memset(board, 0, sizeof(board_t)); - board[0][4] = CHE(KIND_K, BLK); /* ±N */ - board[0][3] = board[0][5] = CHE(KIND_A, BLK); /* ¤h */ - board[0][2] = board[0][6] = CHE(KIND_E, BLK); /* ¶H */ - board[0][0] = board[0][8] = CHE(KIND_R, BLK); /* ¨® */ - board[0][1] = board[0][7] = CHE(KIND_H, BLK); /* °¨ */ - board[2][1] = board[2][7] = CHE(KIND_C, BLK); /* ¥] */ - board[3][0] = board[3][2] = board[3][4] = - board[3][6] = board[3][8] = CHE(KIND_P, BLK); /* ¨ò */ - - board[9][4] = CHE(KIND_K, RED); /* «Ó */ - board[9][3] = board[9][5] = CHE(KIND_A, RED); /* ¥K */ - board[9][2] = board[9][6] = CHE(KIND_E, RED); /* ¬Û */ - board[9][0] = board[9][8] = CHE(KIND_R, RED); /* ¨® */ - board[9][1] = board[9][7] = CHE(KIND_H, RED); /* ØX */ - board[7][1] = board[7][7] = CHE(KIND_C, RED); /* ¬¶ */ - board[6][0] = board[6][2] = board[6][4] = - board[6][6] = board[6][8] = CHE(KIND_P, RED); /* §L */ -} - -static void -chc_prepare_step(ChessInfo* info, const void* step) -{ - const drc_t* move = (const drc_t*) step; - getstep((board_p) info->board, - &move->from, &move->to, info->last_movestr); -} - -static ChessGameResult -chc_movechess(board_t board, const drc_t* move) -{ - int end = (CHE_P(board[move->to.r][move->to.c]) == KIND_K); - - board[move->to.r][move->to.c] = board[move->from.r][move->from.c]; - board[move->from.r][move->from.c] = 0; - - return end ? CHESS_RESULT_WIN : CHESS_RESULT_CONTINUE; -} - -static void -chc_drawstep(ChessInfo* info, const drc_t* move) -{ - ChessDrawLine(info, LTR(info, move->from.r)); - ChessDrawLine(info, LTR(info, move->to.r)); -} - -/* ¨D¨â®y¼Ð¦æ©Î¦C(rowcol)ªº¶ZÂ÷ */ -static int -dist(rc_t from, rc_t to, int rowcol) -{ - int d; - - d = rowcol ? from.c - to.c : from.r - to.r; - return d > 0 ? d : -d; -} - -/* ¨â®y¼Ð(¦æ©Î¦Crowcol)¤¤¶¡¦³´XÁû´Ñ¤l */ -static int -between(board_t board, rc_t from, rc_t to, int rowcol) -{ - int i, rtv = 0; - - if (rowcol) { - if (from.c > to.c) - i = from.c, from.c = to.c, to.c = i; - for (i = from.c + 1; i < to.c; i++) - if (board[to.r][i]) - rtv++; - } else { - if (from.r > to.r) - i = from.r, from.r = to.r, to.r = i; - for (i = from.r + 1; i < to.r; i++) - if (board[i][to.c]) - rtv++; - } - return rtv; -} - -static int -chc_canmove(board_t board, rc_t from, rc_t to) -{ - int i; - int rd, cd, turn; - - if(0 || - !(0<=from.r && from.r<BRD_ROW) || - !(0<=from.c && from.c<BRD_COL) || - !(0<=to.r && to.r<BRD_ROW) || - !(0<=to.c && to.c<BRD_COL)) - return 0; - - rd = dist(from, to, 0); - cd = dist(from, to, 1); - turn = CHE_O(board[from.r][from.c]); - - /* general check */ - if (board[to.r][to.c] && CHE_O(board[to.r][to.c]) == turn) - return 0; - - /* individual check */ - switch (CHE_P(board[from.r][from.c])) { - case KIND_K: /* ±N «Ó */ - if (!(rd == 1 && cd == 0) && - !(rd == 0 && cd == 1)) - return 0; - if ((turn == BLK && to.r > 2) || - (turn == RED && to.r < 7) || - to.c < 3 || to.c > 5) - return 0; - break; - case KIND_A: /* ¤h ¥K */ - if (!(rd == 1 && cd == 1)) - return 0; - if ((turn == BLK && to.r > 2) || - (turn == RED && to.r < 7) || - to.c < 3 || to.c > 5) - return 0; - break; - case KIND_E: /* ¶H ¬Û */ - if (!(rd == 2 && cd == 2)) - return 0; - if ((turn == BLK && to.r > 4) || - (turn == RED && to.r < 5)) - return 0; - /* ©ä¶H»L */ - if (board[CENTER(from.r, to.r)][CENTER(from.c, to.c)]) - return 0; - break; - case KIND_R: /* ¨® */ - if (!(rd > 0 && cd == 0) && - !(rd == 0 && cd > 0)) - return 0; - if (between(board, from, to, rd == 0)) - return 0; - break; - case KIND_H: /* °¨ ØX */ - if (!(rd == 2 && cd == 1) && - !(rd == 1 && cd == 2)) - return 0; - /* ©ä°¨¸} */ - if (rd == 2) { - if (board[CENTER(from.r, to.r)][from.c]) - return 0; - } else { - if (board[from.r][CENTER(from.c, to.c)]) - return 0; - } - break; - case KIND_C: /* ¥] ¬¶ */ - if (!(rd > 0 && cd == 0) && - !(rd == 0 && cd > 0)) - return 0; - i = between(board, from, to, rd == 0); - if ((i > 1) || - (i == 1 && !board[to.r][to.c]) || - (i == 0 && board[to.r][to.c])) - return 0; - break; - case KIND_P: /* ¨ò §L */ - if (!(rd == 1 && cd == 0) && - !(rd == 0 && cd == 1)) - return 0; - if (((turn == BLK && to.r < 5) || - (turn == RED && to.r > 4)) && - cd != 0) - return 0; - if ((turn == BLK && to.r < from.r) || - (turn == RED && to.r > from.r)) - return 0; - break; - } - return 1; -} - -/* §ä turn's king ªº®y¼Ð */ -static int -findking(board_t board, int turn, rc_t * buf) -{ - int i, r, c; - - r = (turn == BLK ? 0 : 7); - for (i = 0; i < 3; r++, i++) - for (c = 3; c < 6; c++) - if (CHE_P(board[r][c]) == KIND_K && - CHE_O(board[r][c]) == turn) { - buf->r = r, buf->c = c; - return 1; - } - /* one's king may be eaten */ - return 0; -} - -static int -chc_iskfk(board_t board) -{ - rc_t from, to; - - if (!findking(board, BLK, &to)) return 0; - if (!findking(board, RED, &from)) return 0; - if (from.c == to.c && between(board, from, to, 0) == 0) - return 1; - return 0; -} - -static int -chc_ischeck(board_t board, int turn) -{ - rc_t from, to; - - if (!findking(board, turn, &to)) return 0; - for (from.r = 0; from.r < BRD_ROW; from.r++) - for (from.c = 0; from.c < BRD_COL; from.c++) - if (board[from.r][from.c] && - CHE_O(board[from.r][from.c]) != turn) - if (chc_canmove(board, from, to)) - return 1; - return 0; -} -/* - * End of the rule function. - */ - -static void -chcusr_put(userec_t* userec, const ChessUser* user) -{ - userec->chc_win = user->win; - userec->chc_lose = user->lose; - userec->chc_tie = user->tie; - userec->chess_elo_rating = user->rating; -} - -static void -chc_init_user(const userinfo_t *uinfo, ChessUser *user) -{ - strlcpy(user->userid, uinfo->userid, sizeof(user->userid)); - user->win = uinfo->chc_win; - user->lose = uinfo->chc_lose; - user->tie = uinfo->chc_tie; - user->rating = uinfo->chess_elo_rating; - if(user->rating == 0) - user->rating = 1500; /* ELO initial value */ - user->orig_rating = user->rating; -} - -static void -chc_init_user_userec(const userec_t *urec, ChessUser *user) -{ - strlcpy(user->userid, urec->userid, sizeof(user->userid)); - user->win = urec->chc_win; - user->lose = urec->chc_lose; - user->tie = urec->chc_tie; - user->rating = urec->chess_elo_rating; - if(user->rating == 0) - user->rating = 1500; /* ELO initial value */ - user->orig_rating = user->rating; -} - -static int -chc_prepare_play(ChessInfo* info) -{ - if (chc_ischeck((board_p) info->board, info->turn)) { - strlcpy(info->warnmsg, ANSI_COLOR(1;31) "±Nx!" ANSI_RESET, - sizeof(info->warnmsg)); - bell(); - } else - info->warnmsg[0] = 0; - - return 0; -} - -static int -chc_select(ChessInfo* info, rc_t scrloc, ChessGameResult* result) -{ - chc_tag_data_t* tag = (chc_tag_data_t*) info->tag; - board_p board = (board_p) info->board; - rc_t loc; - - assert(tag); - - /* transform from screen to internal coordinate */ - if(REDDOWN(info)) { - loc = scrloc; - } else { - loc.r = BRD_ROW-scrloc.r-1; - loc.c = BRD_COL-scrloc.c-1; - } - - if (!tag->selected) { - /* trying to pick something */ - if (board[loc.r][loc.c] && - CHE_O(board[loc.r][loc.c]) == info->turn) { - /* they can pick up this */ - tag->selected = 1; - tag->select = loc; - ChessDrawLine(info, LTR(info, loc.r)); - } - return 0; - } else if (tag->select.r == loc.r && tag->select.c == loc.c) { - /* cancel selection */ - tag->selected = 0; - ChessDrawLine(info, LTR(info, loc.r)); - return 0; - } else if (chc_canmove(board, tag->select, loc)) { - /* moving the chess */ - drc_t moving = { CHESS_STEP_NORMAL, tag->select, loc }; - board_t tmpbrd; - int valid_step = 1; - - if (CHE_P(board[loc.r][loc.c]) == KIND_K) - /* ²¾¨ì¹ï¤è±N«Ó */ - *result = CHESS_RESULT_WIN; - else { - memcpy(tmpbrd, board, sizeof(board_t)); - chc_movechess(tmpbrd, &moving); - valid_step = !chc_iskfk(tmpbrd); - } - - if (valid_step) { - getstep(board, &moving.from, &moving.to, info->last_movestr); - - chc_movechess(board, &moving); - ChessDrawLine(info, LTR(info, moving.from.r)); - ChessDrawLine(info, LTR(info, moving.to.r)); - - ChessHistoryAppend(info, &moving); - ChessStepSend(info, &moving); - - tag->selected = 0; - return 1; - } else { - /* ¤ý¨£¤ý */ - strlcpy(info->warnmsg, - ANSI_COLOR(1;33) "¤£¥i¥H¤ý¨£¤ý" ANSI_RESET, - sizeof(info->warnmsg)); - bell(); - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - return 0; - } - } else - /* nothing happened */ - return 0; -} - -int round_to_int(double x) -{ - /* assume that double cast to int will drop fraction parts */ - if(x>=0) - return (int)(x+0.5); - return (int)(x-0.5); -} - -/* - * ELO rating system - * see http://www.wordiq.com/definition/ELO_rating_system - */ -static void -count_chess_elo_rating(ChessUser* user1, const ChessUser* user2, double myres) -{ - double k; - double exp_res; - int diff; - int newrating; - - if(user1->rating < 1800) - k = 30; - else if(user1->rating < 2000) - k = 25; - else if(user1->rating < 2200) - k = 20; - else if(user1->rating < 2400) - k = 15; - else - k = 10; - - //exp_res = 1.0/(1.0 + pow(10.0, (user2->rating-user1->rating)/400.0)); - //user1->rating += (int)floor(k*(myres-exp_res)+0.5); - diff=(int)user2->rating-(int)user1->rating; - if(diff<=-1000 || diff>=1000) - exp_res=diff>0?0.0:1.0; - else if(diff>=0) - exp_res=elo_exp_tab[diff]; - else - exp_res=1.0-elo_exp_tab[-diff]; - newrating = (int)user1->rating + round_to_int(k*(myres-exp_res)); - if(newrating > 3000) newrating = 3000; - if(newrating < 1) newrating = 1; - user1->rating = newrating; -} - - -/* ¶H´Ñ¥\¯à¶i¤JÂI: - * chc_main: ¹ï«³ - * chc_personal: ¥´ÃÐ - * chc_watch: Æ[´Ñ - * talk.c: ¹ï«³ - */ -void -chc(int s, ChessGameMode mode) -{ - ChessInfo* info = NewChessInfo(&chc_actions, &chc_constants, s, mode); - board_t board; - chc_tag_data_t tag; - - chc_init_board(board); - tag.selected = 0; - - info->board = board; - info->tag = &tag; - - if (info->mode == CHESS_MODE_VERSUS) { - /* Assume that info->user1 is me. */ - info->user1.lose++; - count_chess_elo_rating(&info->user1, &info->user2, 0.0); - passwd_query(usernum, &cuser); - chcusr_put(&cuser, &info->user1); - passwd_update(usernum, &cuser); - } - - if (mode == CHESS_MODE_WATCH) - setutmpmode(CHESSWATCHING); - else - setutmpmode(CHC); - currutmp->sig = SIG_CHC; - - ChessPlay(info); - - DeleteChessInfo(info); -} - -static void -chc_gameend(ChessInfo* info, ChessGameResult result) -{ - ChessUser* const user1 = &info->user1; - ChessUser* const user2 = &info->user2; - - if (info->mode == CHESS_MODE_VERSUS) { - if (info->myturn == RED) { - /* ¥Ñ¬õ¤è§@ log. °Oªº¬O¤U´Ñ«eªºì©l¤À¼Æ */ - /* NOTE, Y¬õ¤èÂ_½u«hµL log */ - time_t t = time(NULL); - char buf[100]; - sprintf(buf, "%s %s(%d,W%d/D%d/L%d) %s %s(%d,W%d/D%d/L%d)\n", - ctime(&t), - user1->userid, user1->rating, user1->win, - user1->tie, user1->lose - 1, - (result == CHESS_RESULT_TIE ? "©M" : - result == CHESS_RESULT_WIN ? "³Ó" : "t"), - user2->userid, user2->rating, user2->win, - user2->tie, user2->lose - 1); - buf[24] = ' '; // replace '\n' - log_file(BBSHOME "/log/chc.log", LOG_CREAT, buf); - } - - user1->rating = user1->orig_rating; - user1->lose--; - if (result == CHESS_RESULT_WIN) { - count_chess_elo_rating(user1, user2, 1.0); - user1->win++; - currutmp->chc_win++; - } else if (result == CHESS_RESULT_LOST) { - count_chess_elo_rating(user1, user2, 0.0); - user1->lose++; - currutmp->chc_lose++; - } else { - count_chess_elo_rating(user1, user2, 0.5); - user1->tie++; - currutmp->chc_tie++; - } - currutmp->chess_elo_rating = user1->rating; - chcusr_put(&cuser, user1); - passwd_update(usernum, &cuser); - } else if (info->mode == CHESS_MODE_REPLAY) { - free(info->board); - free(info->tag); - } -} - -int -chc_main(void) -{ - return ChessStartGame('c', SIG_CHC, "·¡ªeº~¬É¤§ª§"); -} - -int -chc_personal(void) -{ - chc(0, CHESS_MODE_PERSONAL); - return 0; -} - -int -chc_watch(void) -{ - return ChessWatchGame(&chc, CHC, "·¡ªeº~¬É¤§ª§"); -} - -ChessInfo* -chc_replay(FILE* fp) -{ - ChessInfo *info; - char buf[256]; - - info = NewChessInfo(&chc_actions, &chc_constants, - 0, CHESS_MODE_REPLAY); - - while (fgets(buf, sizeof(buf), fp)) { - if (strcmp("</chclog>\n", buf) == 0) - break; - if (buf[0] == '[') { - if (strncmp(buf + 1, "Red", 3) == 0 || - strncmp(buf + 1, "Black", 5) == 0) { - /* /\[(Red|Black) "([a-zA-Z0-9]+)"\]/; $2 */ - userec_t rec; - char *userid; - char *strtok_pos = NULL; - ChessUser *user = - (buf[1] == 'R' ? &info->user1 : &info->user2); - - strtok_r(buf, "\"", &strtok_pos); - userid = strtok_r(NULL, "\"", &strtok_pos); - if (userid != NULL && getuser(userid, &rec)) - chc_init_user_userec(&rec, user); - } - } else { - /* " 1. Ch2-e2 Nb9-c7" */ - drc_t step = { CHESS_STEP_NORMAL }; - const char *p = strchr(buf, '.'); - - if (p == NULL) continue; - - ++p; /* skip '.' */ - while (*p && isspace(*p)) ++p; - if (!*p) continue; - - /* p -> "Ch2-e2 ...." */ - step.from.c = p[1] - 'a'; - step.from.r = BRD_ROW - 1 - (p[2] - '0'); - step.to.c = p[4] - 'a'; - step.to.r = BRD_ROW - 1 - (p[5] - '0'); - -#define INVALID_ROW(R) ((R) < 0 || (R) >= BRD_ROW) -#define INVALID_COL(C) ((C) < 0 || (C) >= BRD_COL) -#define INVALID_LOC(S) (INVALID_ROW(S.r) || INVALID_COL(S.c)) - if (INVALID_LOC(step.from) || INVALID_LOC(step.to)) - continue; - ChessHistoryAppend(info, &step); - - p += 6; - while (*p && isspace(*p)) ++p; - if (!*p) continue; - - /* p -> "Nb9-c7\n" */ - step.from.c = p[1] - 'a'; - step.from.r = BRD_ROW - 1 - (p[2] - '0'); - step.to.c = p[4] - 'a'; - step.to.r = BRD_ROW - 1 - (p[5] - '0'); - - if (INVALID_LOC(step.from) || INVALID_LOC(step.to)) - continue; - ChessHistoryAppend(info, &step); - -#undef INVALID_ROW -#undef INVALID_COL -#undef INVALID_LOC - } - } - - info->board = malloc(sizeof(board_t)); - info->tag = malloc(sizeof(chc_tag_data_t)); - - chc_init_board(info->board); - ((chc_tag_data_t*) info->tag)->selected = 0; - - return info; -} diff --git a/mbbsd/chc_tab.c b/mbbsd/chc_tab.c deleted file mode 100644 index 4bed88ab..00000000 --- a/mbbsd/chc_tab.c +++ /dev/null @@ -1,106 +0,0 @@ -/* $Id$ */ - -/* generated by perl -le 'print 1/(1+10**($_/400)),"," for 0 ..999' */ -/* TODO reduce table size */ -const double elo_exp_tab[1000]={ -0.5, 0.498560888290847, 0.497121800425189, 0.49568276024494, 0.494243791588855, 0.492804918290949, 0.491366164178917, 0.489927553072562, 0.488489108782208, 0.487050855107136, -0.485612815834001, 0.484175014735265, 0.482737475567624, 0.481300222070441, 0.479863277964184, 0.478426666948855, 0.476990412702438, 0.475554538879339, 0.474119069108831, 0.472684026993507, -0.471249436107731, 0.469815319996098, 0.468381702171893, 0.466948606115559, 0.465516055273168, 0.464084073054898, 0.462652682833507, 0.461221907942828, 0.459791771676254, 0.458362297285237, -0.456933507977788, 0.455505426916992, 0.454078077219516, 0.452651481954135, 0.451225664140258, 0.449800646746463, 0.448376452689039, 0.446953104830538, 0.445530625978324, 0.444109038883147, -0.442688366237707, 0.441268630675239, 0.439849854768097, 0.438432061026354, 0.437015271896404, 0.435599509759579, 0.434184796930767, 0.432771155657048, 0.431358608116332, 0.429947176416012, -0.428536882591619, 0.427127748605496, 0.425719796345476, 0.42431304762357, 0.422907524174671, 0.421503247655257, 0.420100239642119, 0.418698521631085, 0.41729811503577, 0.415899041186322, -0.414501321328191, 0.4131049766209, 0.411710028136837, 0.41031649686005, 0.408924403685057, 0.407533769415668, 0.406144614763822, 0.404756960348428, 0.403370826694226, 0.401986234230656, -0.400603203290743, 0.399221754109989, 0.397841906825283, 0.396463681473822, 0.395087097992043, 0.393712176214572, 0.39233893587318, 0.39096739659576, 0.389597577905311, 0.388229499218936, -0.386863179846857, 0.385498638991442, 0.384135895746244, 0.382774969095054, 0.381415877910969, 0.380058640955477, 0.378703276877545, 0.377349804212738, 0.375998241382333, 0.374648606692463, -0.373300918333268, 0.371955194378058, 0.370611452782498, 0.369269711383798, 0.367929987899926, 0.366592299928832, 0.365256664947683, 0.363923100312118, 0.362591623255515, 0.361262250888275, -0.359935000197115, 0.358609888044382, 0.35728693116738, 0.355966146177707, 0.354647549560618, 0.353331157674385, 0.352016986749694, 0.350705052889036, 0.349395372066127, 0.348087960125336, -0.34678283278113, 0.345480005617534, 0.344179494087605, 0.342881313512921, 0.341585479083087, 0.340292005855252, 0.339000908753642, 0.337712202569111, 0.336425901958705, 0.335142021445235, -0.333860575416878, 0.332581578126777, 0.331305043692668, 0.330030986096517, 0.328759419184168, 0.327490356665015, 0.326223812111678, 0.324959798959701, 0.323698330507263, 0.322439419914899, -0.321183080205243, 0.319929324262779, 0.318678164833606, 0.317429614525228, 0.316183685806341, 0.31494039100665, 0.313699742316688, 0.312461751787658, 0.311226431331287, 0.309993792719686, -0.308763847585237, 0.307536607420482, 0.306312083578035, 0.305090287270497, 0.3038712295704, 0.302654921410147, 0.301441373581977, 0.300230596737942, 0.299022601389892, 0.297817397909479, -0.296614996528171, 0.295415407337279, 0.294218640287997, 0.293024705191459, 0.291833611718799, 0.290645369401237, 0.289459987630162, 0.288277475657245, 0.287097842594546, 0.28592109741465, -0.284747248950801, 0.283576305897061, 0.282408276808469, 0.281243170101218, 0.280080994052848, 0.27892175680244, 0.277765466350829, 0.276612130560829, 0.275461757157464, 0.274314353728213, -0.273169927723269, 0.272028486455804, 0.270890037102247, 0.269754586702576, 0.268622142160612, 0.267492710244332, 0.266366297586193, 0.265242910683453, 0.264122555898524, 0.263005239459311, -0.261890967459581, 0.260779745859332, 0.25967158048517, 0.2585664770307, 0.25746444105693, 0.256365477992672, 0.255269593134965, 0.254176791649501, 0.253087078571057, 0.252000458803946, -0.250916937122464, 0.249836518171358, 0.248759206466289, 0.247685006394318, 0.246613922214385, 0.245545958057814, 0.244481117928803, 0.243419405704947, 0.242360825137748, 0.241305379853144, -0.240253073352042, 0.239203909010858, 0.238157890082064, 0.237115019694746, 0.236075300855161, 0.235038736447311, 0.234005329233511, 0.232975081854979, 0.231947996832416, 0.230924076566607, -0.229903323339018, 0.228885739312403, 0.227871326531416, 0.226860086923233, 0.225852022298169, 0.224847134350316, 0.223845424658169, 0.222846894685274, 0.221851545780868, 0.22085937918053, -0.219870396006841, 0.218884597270038, 0.217901983868681, 0.216922556590324, 0.215946316112185, 0.214973263001828, 0.214003397717843, 0.213036720610531, 0.212073231922598, 0.211112931789845, -0.210155820241869, 0.209201897202762, 0.208251162491816, 0.207303615824231, 0.206359256811831, 0.205418084963771, 0.204480099687258, 0.203545300288274, 0.202613685972296, 0.201685255845022, -0.200760008913102, 0.199837944084864, 0.198919060171054, 0.198003355885567, 0.197090829846184, 0.196181480575316, 0.195275306500741, 0.19437230595635, 0.193472477182892, 0.192575818328721, -0.191682327450541, 0.190792002514162, 0.189904841395243, 0.189020841880052, 0.188140001666213, 0.187262318363465, 0.186387789494413, 0.185516412495288, 0.184648184716699, 0.183783103424397, -0.182921165800026, 0.182062368941884, 0.181206709865685, 0.180354185505311, 0.179504792713577, 0.178658528262988, 0.177815388846498, 0.176975371078268, 0.176138471494428, 0.175304686553832, -0.174474012638818, 0.173646446055968, 0.17282198303686, 0.17200061973883, 0.171182352245724, 0.170367176568657, 0.169555088646763, 0.168746084347953, 0.167940159469667, 0.167137309739621, -0.166337530816562, 0.165540818291017, 0.164747167686039, 0.163956574457953, 0.163169033997105, 0.162384541628603, 0.161603092613057, 0.160824682147324, 0.160049305365247, 0.159276957338385, -0.158507633076758, 0.157741327529574, 0.156978035585964, 0.156217752075707, 0.155460471769965, 0.154706189382, 0.153954899567905, 0.153206596927319, 0.15246127600415, 0.151718931287288, -0.150979557211323, 0.150243148157254, 0.149509698453197, 0.148779202375097, 0.148051654147426, 0.147327047943889, 0.146605377888118, 0.145886638054376, 0.14517082246824, 0.144457925107303, -0.14374793990185, 0.143040860735552, 0.142336681446143, 0.141635395826102, 0.140936997623326, 0.140241480541804, 0.139548838242288, 0.138859064342957, 0.138172152420082, 0.137488096008689, -0.13680688860321, 0.136128523658142, 0.135452994588696, 0.134780294771442, 0.134110417544956, 0.13344335621046, 0.132779104032456, 0.132117654239364, 0.131459000024148, 0.130803134544946, -0.130150050925691, 0.12949974225673, 0.128852201595444, 0.128207421966856, 0.12756539636424, 0.12692611774973, 0.126289579054919, 0.125655773181454, 0.125024693001636, 0.124396331359007, -0.123770681068935, 0.123147734919203, 0.12252748567058, 0.121909926057404, 0.121295048788149, 0.120682846545992, 0.120073311989383, 0.119466437752599, 0.118862216446302, 0.118260640658093, -0.117661702953059, 0.117065395874318, 0.116471711943561, 0.115880643661586, 0.115292183508836, 0.114706323945921, 0.11412305741415, 0.113542376336049, 0.112964273115878, 0.112388740140145, -0.111815769778117, 0.111245354382322, 0.110677486289053, 0.110112157818867, 0.109549361277075, 0.108989088954235, 0.108431333126633, 0.107876086056773, 0.107323339993846, 0.106773087174209, -0.106225319821854, 0.105680030148872, 0.10513721035592, 0.104596852632671, 0.104058949158278, 0.103523492101814, 0.102990473622727, 0.102459885871276, 0.101931720988974, 0.101405971109018, -0.100882628356723, 0.100361684849949, 0.0998431326995192, 0.0993269640096439, 0.0988131708783323, 0.098301745397805, 0.0977926796549003, 0.0972859657314782, 0.0967815957048192, 0.0962795616480201, -0.095779855630386, 0.0952824697178176, 0.0947873959731961, 0.0942946264567625, 0.0938041532264949, 0.0933159683384805, 0.0928300638472852, 0.092346431806318, 0.091865064268193, 0.0913859532850863, -0.0909090909090909, 0.090434469192566, 0.0899620801884838, 0.0894919159507723, 0.0890239685346547, 0.0885582299969842, 0.0880946923965764, 0.087633347794537, 0.0871741882545869, 0.0867172058433825, -0.0862623926308338, 0.0858097406904174, 0.0853592420994873, 0.0849108889395813, 0.0844646732967243, 0.0840205872617279, 0.0835786229304866, 0.0831387724042701, 0.0827010277900133, 0.0822653812006012, -0.081831824755152, 0.0814003505792954, 0.0809709508054486, 0.0805436175730883, 0.0801183430290193, 0.0796951193276405, 0.0792739386312066, 0.0788547931100871, 0.0784376749430217, 0.0780225763173731, -0.0776094894293755, 0.0771984064843805, 0.0767893196971002, 0.0763822212918461, 0.0759771035027654, 0.0755739585740745, 0.0751727787602884, 0.0747735563264481, 0.0743762835483439, 0.0739809527127362, -0.0735875561175735, 0.0731960860722064, 0.0728065348975995, 0.0724188949265399, 0.0720331585038426, 0.0716493179865537, 0.0712673657441495, 0.0708872941587333, 0.0705090956252296, 0.070132762551575, -0.0697582873589063, 0.0693856624817454, 0.0690148803681826, 0.0686459334800556, 0.0682788142931266, 0.0679135152972565, 0.0675500289965762, 0.0671883479096555, 0.0668284645696687, 0.0664703715245584, -0.0661140613371956, 0.0657595265855382, 0.065406759862786, 0.0650557537775339, 0.0647065009539218, 0.0643589940317823, 0.064013225666786, 0.063669188530584, 0.0633268753109479, 0.0629862787119077, -0.0626473914538869, 0.062310206273835, 0.061974715925358, 0.0616409131788465, 0.0613087908216012, 0.0609783416579556, 0.0606495585093978, 0.0603224342146881, 0.059996961629976, 0.0596731336289135, -0.0593509431027676, 0.059030382960529, 0.05871144612902, 0.0583941255529991, 0.0580784141952641, 0.057764305036753, 0.0574517910766422, 0.0571408653324433, 0.0568315208400973, 0.0565237506540668, -0.0562175478474267, 0.0559129055119519, 0.0556098167582034, 0.055308274715613, 0.0550082725325648, 0.0547098033764762, 0.0544128604338752, 0.0541174369104776, 0.0538235260312609, 0.0535311210405369, -0.0532402152020224, 0.0529508017989083, 0.0526628741339259, 0.0523764255294125, 0.0520914493273749, 0.0518079388895503, 0.0515258875974668, 0.0512452888525009, 0.0509661360759343, 0.0506884227090081, -0.0504121422129759, 0.0501372880691551, 0.0498638537789762, 0.0495918328640312, 0.0493212188661195, 0.0490520053472927, 0.048784185889898, 0.0485177540966194, 0.0482527035905178, 0.0479890280150698, -0.0477267210342039, 0.0474657763323368, 0.0472061876144066, 0.0469479486059058, 0.0466910530529121, 0.0464354947221181, 0.0461812674008591, 0.0459283648971404, 0.0456767810396624, 0.0454265096778444, -0.0451775446818476, 0.0449298799425962, 0.0446835093717973, 0.0444384269019598, 0.0441946264864115, 0.0439521020993153, 0.043710847735684, 0.0434708574113939, 0.0432321251631971, 0.0429946450487326, -0.0427584111465361, 0.0425234175560489, 0.0422896583976254, 0.0420571278125395, 0.0418258199629894, 0.0415957290321026, 0.0413668492239378, 0.0411391747634878, 0.0409126998966793, 0.0406874188903736, -0.0404633260323643, 0.0402404156313758, 0.0400186820170589, 0.0397981195399872, 0.0395787225716511, 0.0393604855044517, 0.039143402751693, 0.0389274687475736, 0.0387126779471775, 0.0384990248264637, -0.0382865038822547, 0.0380751096322249, 0.0378648366148868, 0.0376556793895778, 0.0374476325364447, 0.0372406906564285, 0.0370348483712476, 0.0368301003233803, 0.0366264411760469, 0.0364238656131903, -0.0362223683394563, 0.0360219440801729, 0.035822587581329, 0.0356242936095519, 0.0354270569520846, 0.035230872416762, 0.0350357348319863, 0.0348416390467019, 0.0346485799303695, 0.0344565523729396, -0.034265551284825, 0.0340755715968728, 0.0338866082603359, 0.0336986562468435, 0.0335117105483713, 0.0333257661772106, 0.0331408181659374, 0.0329568615673801, 0.0327738914545875, 0.0325919029207952, -0.0324108910793922, 0.0322308510638868, 0.0320517780278711, 0.0318736671449865, 0.0316965136088869, 0.0315203126332028, 0.0313450594515039, 0.0311707493172619, 0.030997377503812, 0.0308249393043144, -0.0306534300317155, 0.0304828450187082, 0.0303131796176917, 0.0301444292007309, 0.029976589159516, 0.0298096549053202, 0.0296436218689585, 0.0294784855007451, 0.0293142412704504, 0.0291508846672584, -0.0289884111997226, 0.0288268163957223, 0.0286660958024179, 0.0285062449862065, 0.0283472595326764, 0.0281891350465617, 0.0280318671516965, 0.0278754514909685, 0.0277198837262722, 0.0275651595384624, -0.0274112746273065, 0.027258224711437, 0.0271060055283037, 0.0269546128341251, 0.0268040424038402, 0.0266542900310593, 0.0265053515280152, 0.0263572227255133, 0.0262098994728823, 0.0260633776379237, -0.0259176531068621, 0.0257727217842942, 0.0256285795931381, 0.0254852224745825, 0.0253426463880351, 0.0252008473110712, 0.0250598212393821, 0.0249195641867229, 0.0247800721848603, 0.0246413412835205, -0.024503367550336, 0.0243661470707936, 0.0242296759481806, 0.0240939503035322, 0.0239589662755777, 0.0238247200206873, 0.023691207712818, 0.0235584255434599, 0.0234263697215824, 0.0232950364735793, -0.0231644220432153, 0.0230345226915706, 0.022905334696987, 0.0227768543550127, 0.0226490779783474, 0.0225220018967874, 0.0223956224571704, 0.0222699360233201, 0.0221449389759909, 0.0220206277128122, -0.0218969986482334, 0.0217740482134672, 0.0216517728564348, 0.0215301690417093, 0.0214092332504601, 0.0212889619803967, 0.0211693517457127, 0.0210503990770294, 0.0209321005213396, 0.0208144526419513, -0.0206974520184315, 0.0205810952465492, 0.0204653789382196, 0.0203502997214468, 0.020235854240268, 0.0201220391546963, 0.0200088511406639, 0.0198962868899661, 0.0197843431102039, 0.0196730165247275, -0.0195623038725795, 0.0194522019084381, 0.0193427074025603, 0.0192338171407248, 0.0191255279241757, 0.0190178365695651, 0.0189107399088966, 0.0188042347894684, 0.0186983180738161, 0.0185929866396565, -0.0184882373798301, 0.018384067202245, 0.0182804730298193, 0.018177451800425, 0.0180750004668308, 0.0179731159966456, 0.0178717953722618, 0.0177710355907984, 0.0176708336640446, 0.0175711866184031, -0.0174720914948334, 0.0173735453487957, 0.0172755452501937, 0.0171780882833188, 0.0170811715467935, 0.0169847921535149, 0.0168889472305988, 0.0167936339193229, 0.0166988493750711, 0.0166045907672773, -0.0165108552793692, 0.0164176401087122, 0.016324942466554, 0.0162327595779682, 0.0161410886817987, 0.0160499270306043, 0.0159592718906025, 0.0158691205416144, 0.015779470277009, 0.0156903184036477, -0.0156016622418296, 0.0155134991252354, 0.0154258264008728, 0.0153386414290214, 0.0152519415831777, 0.0151657242500001, 0.0150799868292543, 0.0149947267337584, 0.0149099413893287, 0.0148256282347247, -0.0147417847215951, 0.0146584083144236, 0.0145754964904743, 0.0144930467397378, 0.0144110565648775, 0.0143295234811753, 0.0142484450164782, 0.0141678187111446, 0.0140876421179904, 0.0140079128022362, -0.0139286283414535, 0.0138497863255119, 0.0137713843565254, 0.0136934200488004, 0.0136158910287821, 0.0135387949350018, 0.0134621294180251, 0.0133858921403984, 0.0133100807765973, 0.013234693012974, -0.0131597265477055, 0.0130851790907414, 0.0130110483637521, 0.0129373321000772, 0.012864028044674, 0.0127911339540658, 0.0127186475962907, 0.0126465667508506, 0.0125748892086599, 0.0125036127719948, -0.0124327352544424, 0.0123622544808501, 0.0122921682872752, 0.0122224745209343, 0.0121531710401534, 0.0120842557143176, 0.0120157264238212, 0.011947581060018, 0.0118798175251715, 0.0118124337324056, -0.011745427605655, 0.011678797079616, 0.0116125400996976, 0.0115466546219725, 0.0114811386131282, 0.0114159900504184, 0.0113512069216147, 0.0112867872249579, 0.0112227289691102, 0.0111590301731066, -0.0110956888663077, 0.0110327030883515, 0.0109700708891056, 0.0109077903286204, 0.0108458594770813, 0.0107842764147616, 0.0107230392319756, 0.0106621460290318, 0.010601594916186, 0.0105413840135952, -0.0104815114512704, 0.0104219753690314, 0.0103627739164598, 0.0103039052528536, 0.0102453675471813, 0.0101871589780362, 0.010129277733591, 0.0100717220115526, 0.0100144900191167, 0.00995757997292287, -0.0099009900990099, 0.00984471863277092, 0.00978876381890891, 0.00973312391139234, 0.00967779717341093, 0.00962278187733161, 0.0095680763046546, 0.00951367874596964, 0.00945958750091243, 0.00940580087812116, -0.00935231719519326, 0.00929913477864222, 0.00924625196385471, 0.0091936670950477, 0.00914137852522583, 0.00908938461613893, 0.00903768373823964, 0.00898627427064129, 0.0089351546010758, 0.0088843231258519, -0.00883377824981334, 0.0087835183862974, 0.00873354195709348, 0.00868384739240183, 0.0086344331307925, 0.00858529761916441, 0.00853643931270459, 0.00848785667484757, 0.00843954817723491, 0.00839151229967492, -0.00834374753010252, 0.00829625236453928, 0.00824902530705355, 0.00820206486972079, 0.00815536957258412, 0.0081089379436149, 0.00806276851867354, 0.0080168598414705, 0.00797121046352733, 0.00792581894413801, -0.00788068385033028, 0.00783580375682733, 0.00779117724600942, 0.00774680290787585, 0.00770267934000696, 0.00765880514752633, 0.00761517894306313, 0.00757179934671464, 0.0075286649860089, 0.00748577449586748, -0.00744312651856853, 0.00740071970370979, 0.00735855270817197, 0.0073166241960821, 0.00727493283877711, 0.00723347731476759, 0.00719225630970166, 0.00715126851632898, 0.00711051263446494, 0.00706998737095503, -0.00702969143963924, 0.0069896235613168, 0.00694978246371089, 0.00691016688143358, 0.00687077555595097, 0.00683160723554835, 0.00679266067529564, 0.00675393463701289, 0.00671542788923597, 0.0066771392071824, -0.00663906737271731, 0.00660121117431959, 0.00656356940704816, 0.00652614087250834, 0.00648892437881847, 0.00645191874057659, 0.00641512277882729, 0.00637853532102875, 0.00634215520101984, 0.00630598125898744, -0.00627001234143384, 0.00623424730114438, 0.00619868499715511, 0.0061633242947207, 0.00612816406528242, 0.0060932031864363, 0.00605844054190145, 0.00602387502148844, 0.00598950552106793, 0.00595533094253937, -0.00592135019379986, 0.00588756218871312, 0.00585396584707868, 0.00582056009460114, 0.00578734386285955, 0.00575431608927702, 0.00572147571709038, 0.00568882169532006, 0.00565635297873998, 0.00562406852784773, -0.00559196730883478, 0.00556004829355687, 0.00552831045950453, 0.00549675278977371, 0.00546537427303661, 0.00543417390351256, 0.00540315068093909, 0.00537230361054314, 0.00534163170301236, 0.00531113397446655, -0.00528080944642931, 0.0052506571457997, 0.00522067610482413, 0.00519086536106833, 0.00516122395738946, 0.00513175094190839, 0.00510244536798201, 0.00507330629417583, 0.00504433278423651, 0.00501552390706472, -0.00498687873668797, 0.00495839635223365, 0.00493007583790219, 0.00490191628294032, 0.00487391678161447, 0.00484607643318431, 0.00481839434187639, 0.00479086961685795, 0.00476350137221078, 0.00473628872690529, -0.00470923080477461, 0.00468232673448895, 0.00465557564952992, 0.00462897668816509, 0.00460252899342262, 0.00457623171306605, 0.00455008399956917, 0.00452408501009101, 0.00449823390645103, 0.00447252985510432, -0.00444697202711696, 0.00442155959814155, 0.00439629174839279, 0.00437116766262323, 0.00434618653009909, 0.00432134754457622, 0.0042966499042762, 0.00427209281186252, 0.0042476754744169, 0.00422339710341572, -0.00419925691470652, 0.00417525412848474, 0.0041513879692704, 0.00412765766588505, 0.00410406245142876, 0.00408060156325719, 0.00405727424295889, 0.00403407973633253, 0.00401101729336447, 0.00398808616820623, -0.0039652856191522, 0.00394261490861742, 0.00392007330311544, 0.00389766007323639, 0.00387537449362501, 0.00385321584295892, 0.00383118340392695, 0.00380927646320752, 0.00378749431144725, 0.00376583624323957, -0.00374430155710349, 0.00372288955546247, 0.00370159954462335, 0.00368043083475547, 0.00365938273986982, 0.00363845457779834, 0.00361764567017327, 0.0035969553424067, 0.0035763829236701, 0.00355592774687406, -0.00353558914864806, 0.00351536646932039, 0.00349525905289814, 0.0034752662470473, 0.00345538740307297, 0.00343562187589965, 0.00341596902405165, 0.00339642820963361, 0.00337699879831106, 0.00335768015929115, -0.00333847166530343, 0.00331937269258077, 0.00330038262084031, 0.00328150083326457, 0.00326272671648265, 0.00324405966055149, 0.00322549905893724, 0.00320704430849675, 0.00318869480945912, 0.00317044996540738, -}; diff --git a/mbbsd/chess.c b/mbbsd/chess.c deleted file mode 100644 index a86ca766..00000000 --- a/mbbsd/chess.c +++ /dev/null @@ -1,1762 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -#include "chess.h" -#include <setjmp.h> - -#define assert_not_reached() assert(!"Should never be here!!!") -#define dim(x) (sizeof(x) / sizeof(x[0])) - -#define CHESS_HISTORY_INITIAL_BUFFER_SIZE 300 -#define CHESS_HISTORY_BUFFER_INCREMENT 50 - -#define CHESS_DRAWING_SIDE_ROW 7 -#define CHESS_DRAWING_REAL_TURN_ROW 8 -#define CHESS_DRAWING_REAL_STEP_ROW 9 -#define CHESS_DRAWING_REAL_TIME_ROW1 10 -#define CHESS_DRAWING_REAL_TIME_ROW2 11 -#define CHESS_DRAWING_REAL_WARN_ROW 13 -#define CHESS_DRAWING_MYWIN_ROW 17 -#define CHESS_DRAWING_HISWIN_ROW 18 -#define CHESS_DRAWING_PHOTOED_STEP_ROW 18 -#define CHESS_DRAWING_PHOTOED_TURN_ROW 19 -#define CHESS_DRAWING_PHOTOED_TIME_ROW1 20 -#define CHESS_DRAWING_PHOTOED_TIME_ROW2 21 -#define CHESS_DRAWING_PHOTOED_WARN_ROW 22 - -#define CONNECT_PEER() add_io(info->sock, 0) -#define IGNORE_PEER() add_io(0, 0) - -#define DO_WITHOUT_PEER(TIMEOUT,ACT,ELSE) \ - do { \ - void (*orig_alarm_handler)(int) = \ - Signal(SIGALRM, &SigjmpEnv); \ - IGNORE_PEER(); \ - if(sigsetjmp(sigjmpEnv, 1)) \ - ELSE; \ - else { \ - alarm(TIMEOUT); \ - ACT; \ - } \ - CONNECT_PEER(); \ - Signal(SIGALRM, orig_alarm_handler); \ - } while(0) - -static const char * const ChessHintStr[] = { - " q »{¿éÂ÷¶}", - " p n¨D©M´Ñ", - "¤è¦VÁä ²¾°Ê¹C¼Ð", - "Enter ¿ï¾Ü/²¾°Ê" -}; - -static const struct { - const char* name; - int name_len; - ChessInfo* (*func)(FILE* fp); -} ChessReplayMap[] = { - { "gomoku", 6, &gomoku_replay }, - { "chc", 3, &chc_replay }, - { "go", 2, &gochess_replay }, - { "reversi",7, &reversi_replay }, - { NULL } -}; - -static ChessInfo * CurrentPlayingGameInfo; -static sigjmp_buf sigjmpEnv; - -/* XXX: This is a BAD way to pass information. - * Fix this by handling chess request ourselves. - */ -static ChessTimeLimit * _current_time_limit; - -static void SigjmpEnv(int sig) { siglongjmp(sigjmpEnv, 1); } - -#define CHESS_HISTORY_ENTRY(INFO,N) \ - ((INFO)->history.body + (N) * (INFO)->constants->step_entry_size) -static void -ChessHistoryInit(ChessHistory* history, int entry_size) -{ - history->size = CHESS_HISTORY_INITIAL_BUFFER_SIZE; - history->used = 0; - history->body = - calloc(CHESS_HISTORY_INITIAL_BUFFER_SIZE, - entry_size); -} - -const void* -ChessHistoryRetrieve(ChessInfo* info, int n) -{ - assert(n >= 0 && n < info->history.used); - return CHESS_HISTORY_ENTRY(info, n); -} - -void -ChessHistoryAppend(ChessInfo* info, void* step) -{ - if (info->history.used == info->history.size) - info->history.body = realloc(info->history.body, - (info->history.size += CHESS_HISTORY_BUFFER_INCREMENT) - * info->constants->step_entry_size); - - memmove(CHESS_HISTORY_ENTRY(info, info->history.used), - step, info->constants->step_entry_size); - info->history.used++; -} - -static void -ChessBroadcastListInit(ChessBroadcastList* list) -{ - list->head.next = NULL; -} - -static void -ChessBroadcastListClear(ChessBroadcastList* list) -{ - ChessBroadcastListNode* p = list->head.next; - while (p) { - ChessBroadcastListNode* t = p->next; - close(p->sock); - free(p); - p = t; - } -} - -static ChessBroadcastListNode* -ChessBroadcastListInsert(ChessBroadcastList* list) -{ - ChessBroadcastListNode* p = - (ChessBroadcastListNode*) malloc(sizeof(ChessBroadcastListNode)); - - p->next = list->head.next; - list->head.next = p; - return p; -} - -static void -ChessDrawHelpLine(const ChessInfo* info) -{ - const static char* const HelpStr[] = - { - /* CHESS_MODE_VERSUS, ¹ï«³ */ - ANSI_COLOR(1;33;42) " ¤U´Ñ " - ANSI_COLOR(;31;47) " (¡ö¡ô¡õ¡÷)" ANSI_COLOR(30) " ²¾°Ê " - ANSI_COLOR(31) "(ªÅ¥ÕÁä/ENTER)" ANSI_COLOR(30) " ¤U¤l " - ANSI_COLOR(31) "(q)" ANSI_COLOR(30) "»{¿é " - ANSI_COLOR(31) "(p)" ANSI_COLOR(30) "µê¤â/©M´Ñ " - ANSI_COLOR(31) "(u)" ANSI_COLOR(30) "®¬´Ñ " - ANSI_RESET, - - /* CHESS_MODE_WATCH, Æ[´Ñ */ - ANSI_COLOR(1;33;42) " Æ[´Ñ " - ANSI_COLOR(;31;47) " (¡ö¡÷)" ANSI_COLOR(30) " «e«á¤@¨B " - ANSI_COLOR(31) "(¡ô¡õ)" ANSI_COLOR(30) " «e«á¤Q¨B " - ANSI_COLOR(31) "(PGUP/PGDN)" ANSI_COLOR(30) " ³Ìªì/¥Ø«e½L± " - ANSI_COLOR(31) "(q)" ANSI_COLOR(30) "Â÷¶} " - ANSI_RESET, - - /* CHESS_MODE_PERSONAL, ¥´ÃÐ */ - ANSI_COLOR(1;33;42) " ¥´ÃÐ " - ANSI_COLOR(;31;47) " (¡ö¡ô¡õ¡÷)" ANSI_COLOR(30) " ²¾°Ê " - ANSI_COLOR(31) "(ªÅ¥ÕÁä/ENTER)" ANSI_COLOR(30) " ¤U¤l " - ANSI_COLOR(31) "(q)" ANSI_COLOR(30) "Â÷¶} " - ANSI_COLOR(31) "(u)" ANSI_COLOR(30) "®¬´Ñ " - ANSI_RESET, - - /* CHESS_MODE_REPLAY, ¬ÝÃÐ */ - ANSI_COLOR(1;33;42) " ¬ÝÃÐ " - ANSI_COLOR(;31;47) " (¡ö¡÷)" ANSI_COLOR(30) " «e«á¤@¨B " - ANSI_COLOR(31) "(¡ô¡õ)" ANSI_COLOR(30) " «e«á¤Q¨B " - ANSI_COLOR(31) "(PGUP/PGDN)" ANSI_COLOR(30) " ³Ìªì/¥Ø«e½L± " - ANSI_COLOR(31) "(q)" ANSI_COLOR(30) "Â÷¶} " - ANSI_RESET, - }; - - mouts(b_lines, 0, HelpStr[info->mode]); - info->actions->drawline(info, b_lines); -} - -void -ChessDrawLine(const ChessInfo* info, int line) -{ -#define DRAWLINE(LINE) \ - do { \ - move((LINE), 0); \ - clrtoeol(); \ - info->actions->drawline(info, (LINE)); \ - } while (0) - - if (line == b_lines) { - ChessDrawHelpLine(info); - return; - } else if (line == CHESS_DRAWING_TURN_ROW) - line = info->photo ? - CHESS_DRAWING_PHOTOED_TURN_ROW : - CHESS_DRAWING_REAL_TURN_ROW; - else if (line == CHESS_DRAWING_TIME_ROW) { - if(info->photo) { - DRAWLINE(CHESS_DRAWING_PHOTOED_TIME_ROW1); - DRAWLINE(CHESS_DRAWING_PHOTOED_TIME_ROW2); - } else { - DRAWLINE(CHESS_DRAWING_REAL_TIME_ROW1); - DRAWLINE(CHESS_DRAWING_REAL_TIME_ROW2); - } - return; - } else if (line == CHESS_DRAWING_WARN_ROW) - line = info->photo ? - CHESS_DRAWING_PHOTOED_WARN_ROW : - CHESS_DRAWING_REAL_WARN_ROW; - else if (line == CHESS_DRAWING_STEP_ROW) - line = info->photo ? - CHESS_DRAWING_PHOTOED_STEP_ROW : - CHESS_DRAWING_REAL_STEP_ROW; - - DRAWLINE(line); - -#undef DRAWLINE -} - -void -ChessRedraw(const ChessInfo* info) -{ - int i; - clear(); - for (i = 0; i <= b_lines; ++i) - ChessDrawLine(info, i); -} - -inline static int -ChessTimeCountDownCalc(ChessInfo* info, int who, int length) -{ - info->lefttime[who] -= length; - - if (!info->timelimit) /* traditional mode, only left time is considered */ - return info->lefttime[who] < 0; - - if (info->lefttime[who] < 0) { /* only allowed when in free time */ - if (info->lefthand[who]) - return 1; - info->lefttime[who] += info->timelimit->limit_time; - info->lefthand[who] = info->timelimit->limit_hand; - - return (info->lefttime[who] < 0); - } - - return 0; -} - -int -ChessTimeCountDown(ChessInfo* info, int who, int length) -{ - int result = ChessTimeCountDownCalc(info, who, length); - ChessDrawLine(info, CHESS_DRAWING_TIME_ROW); - return result; -} - -void -ChessStepMade(ChessInfo* info, int who) -{ - if (!info->timelimit) - info->lefttime[who] = info->constants->traditional_timeout; - else if ( - (info->lefthand[who] && (--(info->lefthand[who]) == 0) && - info->timelimit->time_mode == CHESS_TIMEMODE_COUNTING) - || - (info->lefthand[who] == 0 && info->lefttime[who] <= 0) - ) { - info->lefthand[who] = info->timelimit->limit_hand; - info->lefttime[who] = info->timelimit->limit_time; - } -} - -/* - * Start of the network communication function. - */ -inline static ChessStepType -ChessRecvMove(ChessInfo* info, int sock, void *step) -{ - if (read(sock, step, info->constants->step_entry_size) - != info->constants->step_entry_size) - return CHESS_STEP_FAILURE; - return *(ChessStepType*) step; -} - -inline static int -ChessSendMove(ChessInfo* info, int sock, const void *step) -{ - if (write(sock, step, info->constants->step_entry_size) - != info->constants->step_entry_size) - return 0; - return 1; -} - -inline static int -ChessStepSendOpposite(ChessInfo* info, const void* step) -{ - void (*orig_handler)(int); - int result = 1; - - /* fd 0 is the socket to user, it means no oppisite available. - * (Might be personal play) */ - if (info->sock == 0) - return 1; - - orig_handler = Signal(SIGPIPE, SIG_IGN); - - if (!ChessSendMove(info, info->sock, step)) - result = 0; - - Signal(SIGPIPE, orig_handler); - return result; -} - -inline static void -ChessStepBroadcast(ChessInfo* info, const void *step) -{ - ChessBroadcastListNode *p = &(info->broadcast_list.head); - void (*orig_handler)(int); - - orig_handler = Signal(SIGPIPE, SIG_IGN); - - while(p->next){ - if (!ChessSendMove(info, p->next->sock, step)) { - /* remove viewer */ - ChessBroadcastListNode *tmp = p->next->next; - free(p->next); - p->next = tmp; - } else - p = p->next; - } - - Signal(SIGPIPE, orig_handler); -} - -int -ChessStepSend(ChessInfo* info, const void* step) -{ - /* send to opposite... */ - if (!ChessStepSendOpposite(info, step)) - return 0; - - /* and watchers */ - ChessStepBroadcast(info, step); - - return 1; -} - -int -ChessMessageSend(ChessInfo* info, ChessStepType type) -{ - return ChessStepSend(info, &type); -} - -static inline int -ChessCheckAlive(ChessInfo* info) -{ - ChessStepType type = CHESS_STEP_NOP; - return ChessStepSendOpposite(info, &type); -} - -ChessStepType -ChessStepReceive(ChessInfo* info, void* step) -{ - ChessStepType result = ChessRecvMove(info, info->sock, step); - - /* automatical routing */ - if (result != CHESS_STEP_FAILURE) - ChessStepBroadcast(info, step); - - /* and logging */ - if (result == CHESS_STEP_NORMAL || result == CHESS_STEP_PASS) - ChessHistoryAppend(info, step); - - return result; -} - -inline static void -ChessReplayUntil(ChessInfo* info, int n) -{ - const void* step; - - if (n <= info->current_step) - return; - - while (info->current_step < n - 1) { - info->actions->apply_step(info->board, - ChessHistoryRetrieve(info, info->current_step)); - info->current_step++; - } - - /* spcial for last one to maintian information correct */ - step = ChessHistoryRetrieve(info, info->current_step); - - if (info->mode == CHESS_MODE_WATCH || info->mode == CHESS_MODE_REPLAY) - info->turn = info->current_step & 1; - info->actions->prepare_step(info, step); - info->actions->apply_step(info->board, step); - info->current_step++; -} - -static int -ChessAnswerRequest(ChessInfo* info, const char* req_name) -{ - char buf[4]; - char msg[64]; - - snprintf(info->warnmsg, sizeof(info->warnmsg), - ANSI_COLOR(1;31) "n¨D%s!" ANSI_RESET, req_name); - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - bell(); - - snprintf(msg, sizeof(msg), - "¹ï¤èn¨D%s¡A¬O§_±µ¨ü?(y/N)", req_name); - DO_WITHOUT_PEER(30, - getdata(b_lines, 0, msg, buf, sizeof(buf), DOECHO), - buf[0] = 'n'); - ChessDrawHelpLine(info); - - info->warnmsg[0] = 0; - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - - if (buf[0] == 'y' || buf[0] == 'Y') - return 1; - else - return 0; -} - -ChessGameResult -ChessPlayFuncMy(ChessInfo* info) -{ - int last_time = now; - int endturn = 0; - ChessGameResult game_result = CHESS_RESULT_CONTINUE; - int ch; -#ifdef DBCSAWARE - int move_count = 0; -#endif - - info->pass[(int) info->turn] = 0; - bell(); - - while (!endturn) { - ChessStepType result; - - ChessDrawLine(info, CHESS_DRAWING_TIME_ROW); - info->actions->movecur(info->cursor.r, info->cursor.c); - oflush(); - - ch = igetch(); - if (ChessTimeCountDown(info, 0, now - last_time)) { - /* ran out of time */ - game_result = CHESS_RESULT_LOST; - endturn = 1; - break; - } - last_time = now; - - switch (ch) { - case I_OTHERDATA: - result = ChessStepReceive(info, &info->step_tmp); - - if (result == CHESS_STEP_FAILURE || - result == CHESS_STEP_DROP) { - game_result = CHESS_RESULT_WIN; - endturn = 1; - } else if (result == CHESS_STEP_TIE_ACC) { - game_result = CHESS_RESULT_TIE; - endturn = 1; - } else if (result == CHESS_STEP_TIE_REJ) { - strcpy(info->warnmsg, ANSI_COLOR(1;31) "¨D©M³Q©Ú!" ANSI_RESET); - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - } else if (result == CHESS_STEP_UNDO) { - if (ChessAnswerRequest(info, "®¬´Ñ")) { - ChessMessageSend(info, CHESS_STEP_UNDO_ACC); - - info->actions->init_board(info->board); - info->current_step = 0; - ChessReplayUntil(info, info->history.used - 1); - info->history.used--; - - ChessRedraw(info); - - endturn = 1; - } else - ChessMessageSend(info, CHESS_STEP_UNDO_REJ); - } else if (result == CHESS_STEP_NORMAL || - result == CHESS_STEP_SPECIAL) { - info->actions->prepare_step(info, &info->step_tmp); - game_result = - info->actions->apply_step(info->board, - &info->step_tmp); - info->actions->drawstep(info, &info->step_tmp); - endturn = 1; - ChessStepMade(info, 0); - } - break; - - case KEY_UP: - info->cursor.r--; - if (info->cursor.r < 0) - info->cursor.r = info->constants->board_height - 1; - break; - - case KEY_DOWN: - info->cursor.r++; - if (info->cursor.r >= info->constants->board_height) - info->cursor.r = 0; - break; - - case KEY_LEFT: -#ifdef DBCSAWARE - if (!ISDBCSAWARE()) { - if (++move_count >= 2) - move_count = 0; - else - break; - } -#endif /* defined(DBCSAWARE) */ - - info->cursor.c--; - if (info->cursor.c < 0) - info->cursor.c = info->constants->board_width - 1; - break; - - case KEY_RIGHT: -#ifdef DBCSAWARE - if (!ISDBCSAWARE()) { - if (++move_count >= 2) - move_count = 0; - else - break; - } -#endif /* defined(DBCSAWARE) */ - - info->cursor.c++; - if (info->cursor.c >= info->constants->board_width) - info->cursor.c = 0; - break; - - case 'q': - { - char buf[4]; - - DO_WITHOUT_PEER(30, - getdata(b_lines, 0, - info->mode == CHESS_MODE_PERSONAL ? - "¬O§_¯uªºnÂ÷¶}?(y/N)" : - "¬O§_¯uªºn»{¿é?(y/N)", - buf, sizeof(buf), DOECHO), - buf[0] = 'n'); - ChessDrawHelpLine(info); - - if (buf[0] == 'y' || buf[0] == 'Y') { - game_result = CHESS_RESULT_LOST; - endturn = 1; - } - } - break; - - case 'p': - if (info->constants->pass_is_step) { - ChessStepType type = CHESS_STEP_PASS; - ChessHistoryAppend(info, &type); - strcpy(info->last_movestr, "µê¤â"); - - info->pass[(int) info->turn] = 1; - ChessMessageSend(info, CHESS_STEP_PASS); - endturn = 1; - } else if (info->mode != CHESS_MODE_PERSONAL) { - char buf[4]; - - DO_WITHOUT_PEER(30, - getdata(b_lines, 0, "¬O§_¯uªºn©M´Ñ?(y/N)", - buf, sizeof(buf), DOECHO), - buf[0] = 'n'); - ChessDrawHelpLine(info); - - if (buf[0] == 'y' || buf[1] == 'Y') { - ChessMessageSend(info, CHESS_STEP_TIE); - strlcpy(info->warnmsg, - ANSI_COLOR(1;33) "n¨D©M´Ñ!" ANSI_RESET, - sizeof(info->warnmsg)); - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - bell(); - } - } - break; - - case 'u': - if (info->mode == CHESS_MODE_PERSONAL && info->history.used > 0) { - ChessMessageSend(info, CHESS_STEP_UNDO_ACC); - - info->actions->init_board(info->board); - info->current_step = 0; - ChessReplayUntil(info, info->history.used - 1); - info->history.used--; - - ChessRedraw(info); - - endturn = 1; - } - break; - - case '\r': - case '\n': - case ' ': - endturn = info->actions->select(info, info->cursor, &game_result); - break; - - case I_TIMEOUT: - break; - - case KEY_UNKNOWN: - break; - - default: - if (info->actions->process_key) { - DO_WITHOUT_PEER(30, - endturn = - info->actions->process_key(info, ch, &game_result), - ); - } - } - } - ChessTimeCountDown(info, 0, now - last_time); - ChessStepMade(info, 0); - ChessDrawLine(info, CHESS_DRAWING_TIME_ROW); - ChessDrawLine(info, CHESS_DRAWING_STEP_ROW); - return game_result; -} - -static ChessGameResult -ChessPlayFuncHis(ChessInfo* info) -{ - int last_time = now; - int endturn = 0; - ChessGameResult game_result = CHESS_RESULT_CONTINUE; - - while (!endturn) { - ChessStepType result; - int ch; - - if (ChessTimeCountDown(info, 1, now - last_time)) { - info->lefttime[1] = 0; - - /* to make him break out igetch() */ - ChessMessageSend(info, CHESS_STEP_NOP); - } - last_time = now; - - ChessDrawLine(info, CHESS_DRAWING_TIME_ROW); - move(1, 0); - oflush(); - - switch (ch = igetch()) { - case 'q': - { - char buf[4]; - DO_WITHOUT_PEER(30, - getdata(b_lines, 0, "¬O§_¯uªºn»{¿é?(y/N)", - buf, sizeof(buf), DOECHO), - buf[0] = 'n'); - ChessDrawHelpLine(info); - - if (buf[0] == 'y' || buf[0] == 'Y') { - game_result = CHESS_RESULT_LOST; - endturn = 1; - } - } - break; - - case 'u': - if (info->history.used > 0) { - strcpy(info->warnmsg, ANSI_COLOR(1;31) "n¨D®¬´Ñ!" ANSI_RESET); - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - - ChessMessageSend(info, CHESS_STEP_UNDO); - } - break; - - case I_OTHERDATA: - result = ChessStepReceive(info, &info->step_tmp); - - if (result == CHESS_STEP_FAILURE || - result == CHESS_STEP_DROP) { - game_result = CHESS_RESULT_WIN; - endturn = 1; - } else if (result == CHESS_STEP_PASS) { - strcpy(info->last_movestr, "µê¤â"); - - info->pass[(int) info->turn] = 1; - endturn = 1; - } else if (result == CHESS_STEP_TIE) { - if (ChessAnswerRequest(info, "©M´Ñ")) { - ChessMessageSend(info, CHESS_STEP_TIE_ACC); - - game_result = CHESS_RESULT_TIE; - endturn = 1; - } else - ChessMessageSend(info, CHESS_STEP_TIE_REJ); - } else if (result == CHESS_STEP_NORMAL || - result == CHESS_STEP_SPECIAL) { - info->actions->prepare_step(info, &info->step_tmp); - switch (info->actions->apply_step(info->board, &info->step_tmp)) { - case CHESS_RESULT_LOST: - game_result = CHESS_RESULT_WIN; - break; - - case CHESS_RESULT_WIN: - game_result = CHESS_RESULT_LOST; - break; - - default: - game_result = CHESS_RESULT_CONTINUE; - } - endturn = 1; - info->pass[(int) info->turn] = 0; - ChessStepMade(info, 1); - info->actions->drawstep(info, &info->step_tmp); - } else if (result == CHESS_STEP_UNDO_ACC) { - strcpy(info->warnmsg, ANSI_COLOR(1;31) "±µ¨ü®¬´Ñ!" ANSI_RESET); - - info->actions->init_board(info->board); - info->current_step = 0; - ChessReplayUntil(info, info->history.used - 1); - info->history.used--; - - ChessRedraw(info); - bell(); - - endturn = 1; - } else if (result == CHESS_STEP_UNDO_REJ) { - strcpy(info->warnmsg, ANSI_COLOR(1;31) "®¬´Ñ³Q©Ú!" ANSI_RESET); - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - } - - case I_TIMEOUT: - break; - - case KEY_UNKNOWN: - break; - - default: - if (info->actions->process_key) { - DO_WITHOUT_PEER(30, - endturn = - info->actions->process_key(info, ch, &game_result), - ); - } - } - } - ChessTimeCountDown(info, 1, now - last_time); - ChessDrawLine(info, CHESS_DRAWING_TIME_ROW); - ChessDrawLine(info, CHESS_DRAWING_STEP_ROW); - return game_result; -} - -static ChessGameResult -ChessPlayFuncWatch(ChessInfo* info) -{ - int end_watch = 0; - - while (!end_watch) { - ChessStepType result; - - info->actions->prepare_play(info); - if (info->sock == -1) - strlcpy(info->warnmsg, ANSI_COLOR(1;33) "´Ñ§½¤wµ²§ô" ANSI_RESET, - sizeof(info->warnmsg)); - - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - ChessDrawLine(info, CHESS_DRAWING_STEP_ROW); - move(1, 0); - - switch (igetch()) { - case I_OTHERDATA: /* new step */ - result = ChessStepReceive(info, &info->step_tmp); - - if (result == CHESS_STEP_FAILURE) { - IGNORE_PEER(); - info->sock = -1; - break; - } else if (result == CHESS_STEP_UNDO_ACC) { - if (info->current_step == info->history.used) { - /* at head but redo-ed */ - info->actions->init_board(info->board); - info->current_step = 0; - ChessReplayUntil(info, info->history.used - 1); - ChessRedraw(info); - } - info->history.used--; - } else if (result == CHESS_STEP_NORMAL || - result == CHESS_STEP_SPECIAL) { - if (info->current_step == info->history.used - 1) { - /* was watching up-to-date board */ - info->turn = info->current_step++ & 1; - info->actions->prepare_step(info, &info->step_tmp); - info->actions->apply_step(info->board, &info->step_tmp); - info->actions->drawstep(info, &info->step_tmp); - } - } else if (result == CHESS_STEP_PASS) - strcpy(info->last_movestr, "µê¤â"); - - break; - - case KEY_LEFT: /* ©¹«e¤@¨B */ - if (info->current_step == 0) - bell(); - else { - /* TODO: implement without re-apply all steps */ - int current = info->current_step; - - info->actions->init_board(info->board); - info->current_step = 0; - - ChessReplayUntil(info, current - 1); - ChessRedraw(info); - } - break; - - case KEY_RIGHT: /* ©¹«á¤@¨B */ - if (info->current_step == info->history.used) - bell(); - else { - const void* step = - ChessHistoryRetrieve(info, info->current_step); - info->turn = info->current_step++ & 1; - info->actions->prepare_step(info, step); - info->actions->apply_step(info->board, step); - info->actions->drawstep(info, step); - } - break; - - case KEY_UP: /* ©¹«e¤Q¨B */ - if (info->current_step == 0) - bell(); - else { - /* TODO: implement without re-apply all steps */ - int current = info->current_step; - - info->actions->init_board(info->board); - info->current_step = 0; - - ChessReplayUntil(info, current - 10); - - ChessRedraw(info); - } - break; - - case KEY_DOWN: /* ©¹«á¤Q¨B */ - if (info->current_step == info->history.used) - bell(); - else { - ChessReplayUntil(info, - MIN(info->current_step + 10, info->history.used)); - ChessRedraw(info); - } - break; - - case KEY_PGUP: /* °_©l½L± */ - if (info->current_step == 0) - bell(); - else { - info->actions->init_board(info->board); - info->current_step = 0; - ChessRedraw(info); - } - break; - - case KEY_PGDN: /* ³Ì·s½L± */ - if (info->current_step == info->history.used) - bell(); - else { - ChessReplayUntil(info, info->history.used); - ChessRedraw(info); - } - break; - - case 'q': - end_watch = 1; - } - } - - return CHESS_RESULT_END; -} - -static void -ChessWatchRequest(int sig) -{ - int sock = establish_talk_connection(&SHM->uinfo[currutmp->destuip]); - ChessBroadcastListNode* node; - - if (sock < 0 || !CurrentPlayingGameInfo) - return; - - node = ChessBroadcastListInsert(&CurrentPlayingGameInfo->broadcast_list); - node->sock = sock; - -#define SEND(X) write(sock, &(X), sizeof(X)) - SEND(CurrentPlayingGameInfo->myturn); - SEND(CurrentPlayingGameInfo->turn); - - if (!CurrentPlayingGameInfo->timelimit) - write(sock, "T", 1); - else { - write(sock, "L", 1); - SEND(*(CurrentPlayingGameInfo->timelimit)); - } - - SEND(CurrentPlayingGameInfo->history.used); - write(sock, CurrentPlayingGameInfo->history.body, - CurrentPlayingGameInfo->constants->step_entry_size - * CurrentPlayingGameInfo->history.used); -#undef SEND -} - -static void -ChessReceiveWatchInfo(ChessInfo* info) -{ - char time_mode; -#define RECV(X) read(info->sock, &(X), sizeof(X)) - RECV(info->myturn); - RECV(info->turn); - - RECV(time_mode); - if (time_mode == 'L') { - info->timelimit = (ChessTimeLimit*) malloc(sizeof(ChessTimeLimit)); - RECV(*(info->timelimit)); - } - - RECV(info->history.used); - for (info->history.size = CHESS_HISTORY_INITIAL_BUFFER_SIZE; - info->history.size < info->history.used; - info->history.size += CHESS_HISTORY_BUFFER_INCREMENT); - info->history.body = - calloc(info->history.size, info->constants->step_entry_size); - read(info->sock, info->history.body, - info->history.used * info->constants->step_entry_size); -#undef RECV -} - -static void -ChessGenLogGlobal(ChessInfo* info, ChessGameResult result) -{ - fileheader_t log_header; - FILE *fp; - char fname[PATHLEN]; - int bid; - - if ((bid = getbnum(info->constants->log_board)) == 0) - return; - - setbpath(fname, info->constants->log_board); - stampfile(fname, &log_header); - - fp = fopen(fname, "w"); - if (fp != NULL) { - strlcpy(log_header.owner, "[´ÑÃо÷¾¹¤H]", sizeof(log_header.owner)); - snprintf(log_header.title, sizeof(log_header.title), "[´ÑÃÐ] %s VS %s", - info->user1.userid, info->user2.userid); - - fprintf(fp, "§@ªÌ: %s ¬ÝªO: %s\n¼ÐÃD: %s \n", log_header.owner, info->constants->log_board, log_header.title); - fprintf(fp, "®É¶¡: %s\n", ctime4(&now)); - - info->actions->genlog(info, fp, result); - fclose(fp); - - setbdir(fname, info->constants->log_board); - append_record(fname, &log_header, sizeof(log_header)); - - setbtotal(bid); - } -} - -static void -ChessGenLogUser(ChessInfo* info, ChessGameResult result) -{ - fileheader_t log_header; - FILE *fp; - char fname[PATHLEN]; - - sethomepath(fname, cuser.userid); - stampfile(fname, &log_header); - - fp = fopen(fname, "w"); - if (fp != NULL) { - info->actions->genlog(info, fp, result); - fclose(fp); - - snprintf(log_header.owner, sizeof(log_header.owner), "[%s]", - info->constants->chess_name); - if(info->myturn == 0) - sprintf(log_header.title, "%s V.S. %s", - info->user1.userid, info->user2.userid); - else - sprintf(log_header.title, "%s V.S. %s", - info->user2.userid, info->user1.userid); - log_header.filemode = 0; - - sethomedir(fname, cuser.userid); - append_record_forward(fname, &log_header, sizeof(log_header), - cuser.userid); - } -} - -static void -ChessGenLog(ChessInfo* info, ChessGameResult result) -{ - char a = 0; - if (info->mode == CHESS_MODE_VERSUS && info->myturn == 0 && - info->constants->log_board) { - ChessGenLogGlobal(info, result); - } - - a = getans((cuser.uflag & DEFBACKUP_FLAG) ? - "¬O§_±N´ÑÃбH¦^«H½c¡H [Y/n]" : - "¬O§_±N´ÑÃбH¦^«H½c¡H [y/N]"); - - if (TOBACKUP(a)) - ChessGenLogUser(info, result); -} - -void -ChessPlay(ChessInfo* info) -{ - ChessGameResult game_result; - void (*old_handler)(int); - const char* game_result_str = 0; - sigset_t old_sigset; - - if (info == NULL) - return; - - if (!ChessCheckAlive(info)) { - if (info->sock) - close(info->sock); - return; - } - - /* XXX */ - if (!info->timelimit) { - info->timelimit = _current_time_limit; - _current_time_limit = NULL; - } - - CurrentPlayingGameInfo = info; - - { - char buf[4] = ""; - sigset_t sigset; - - if(info->mode == CHESS_MODE_VERSUS) - getdata(b_lines, 0, "¬O§_±µ¨üÆ[´Ñ? (Y/n)", buf, sizeof(buf), DOECHO); - if(buf[0] == 'n' || buf[0] == 'N') - old_handler = Signal(SIGUSR1, SIG_IGN); - else - old_handler = Signal(SIGUSR1, &ChessWatchRequest); - - sigemptyset(&sigset); - sigaddset(&sigset, SIGUSR1); - sigprocmask(SIG_UNBLOCK, &sigset, &old_sigset); - } - - if (info->mode == CHESS_MODE_WATCH) { - int i; - for (i = 0; i < info->history.used; ++i) - info->actions->apply_step(info->board, - ChessHistoryRetrieve(info, i)); - info->current_step = info->history.used; - } - - /* playing initialization */ - ChessRedraw(info); - info->turn = 1; - info->lefttime[0] = info->lefttime[1] = info->timelimit ? - info->timelimit->free_time : info->constants->traditional_timeout; - info->lefthand[0] = info->lefthand[1] = 0; - - /* main loop */ - CONNECT_PEER(); - for (game_result = CHESS_RESULT_CONTINUE; - game_result == CHESS_RESULT_CONTINUE; - info->turn ^= 1) { - if (info->actions->prepare_play(info)) - info->pass[(int) info->turn] = 1; - else { - ChessDrawLine(info, CHESS_DRAWING_TURN_ROW); - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - game_result = info->play_func[(int) info->turn](info); - } - - if (info->pass[0] && info->pass[1]) - game_result = CHESS_RESULT_END; - } - - if (game_result == CHESS_RESULT_END && - info->actions->post_game && - (info->mode == CHESS_MODE_VERSUS || - info->mode == CHESS_MODE_PERSONAL)) - game_result = info->actions->post_game(info); - - IGNORE_PEER(); - - if (info->sock) - close(info->sock); - - /* end processing */ - if (info->mode == CHESS_MODE_VERSUS) { - switch (game_result) { - case CHESS_RESULT_WIN: - game_result_str = "¹ï¤è»{¿é¤F!"; - break; - - case CHESS_RESULT_LOST: - game_result_str = "§A»{¿é¤F!"; - break; - - case CHESS_RESULT_TIE: - game_result_str = "©M´Ñ"; - break; - - default: - assert_not_reached(); - } - } else if (info->mode == CHESS_MODE_WATCH) - game_result_str = "µ²§ôÆ[´Ñ"; - else if (info->mode == CHESS_MODE_PERSONAL) - game_result_str = "µ²§ô¥´ÃÐ"; - else if (info->mode == CHESS_MODE_REPLAY) - game_result_str = "µ²§ô¬ÝÃÐ"; - - if (game_result_str) { - strlcpy(info->warnmsg, game_result_str, sizeof(info->warnmsg)); - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - } - - info->actions->gameend(info, game_result); - - if (info->mode != CHESS_MODE_REPLAY) - ChessGenLog(info, game_result); - - // currutmp->sig = -1; - sigprocmask(SIG_SETMASK, &old_sigset, NULL); - Signal(SIGUSR1, old_handler); - - CurrentPlayingGameInfo = NULL; -} - -static userinfo_t* -ChessSearchUser(int sig, const char* title) -{ - char uident[16]; - userinfo_t *uin; - - stand_title(title); - CompleteOnlineUser(msg_uid, uident); - if (uident[0] == '\0') - return NULL; - - if ((uin = search_ulist_userid(uident)) == NULL) - return NULL; - - if (sig >= 0) - uin->sig = sig; - return uin; -} - -int -ChessStartGame(char func_char, int sig, const char* title) -{ - userinfo_t *uin; - char buf[4]; - - if ((uin = ChessSearchUser(sig, title)) == NULL) - return -1; - uin->turn = 1; - currutmp->turn = 0; - strlcpy(uin->mateid, currutmp->userid, sizeof(uin->mateid)); - strlcpy(currutmp->mateid, uin->userid, sizeof(currutmp->mateid)); - - stand_title(title); - buf[0] = 0; - getdata(2, 0, "¨Ï¥Î¶Ç²Î¼Ò¦¡ (T), ®É¨B¼Ò¦¡ (L) ©Î¬O Ū¬í¼Ò¦¡ (C)? (T/l/c)", - buf, 3, DOECHO); - - if (buf[0] == 'l' || buf[0] == 'L' || - buf[0] == 'c' || buf[0] == 'C') { - - _current_time_limit = (ChessTimeLimit*) malloc(sizeof(ChessTimeLimit)); - if (buf[0] == 'l' || buf[0] == 'L') - _current_time_limit->time_mode = CHESS_TIMEMODE_MULTIHAND; - else - _current_time_limit->time_mode = CHESS_TIMEMODE_COUNTING; - - do { - getdata_str(3, 0, "½Ð³]©w§½®É (¦Û¥Ñ®É¶¡) ¥H¤ÀÄÁ¬°³æ¦ì:", - buf, 3, DOECHO, "30"); - _current_time_limit->free_time = atoi(buf); - } while (_current_time_limit->free_time < 0 || _current_time_limit->free_time > 90); - _current_time_limit->free_time *= 60; /* minute -> second */ - - if (_current_time_limit->time_mode == CHESS_TIMEMODE_MULTIHAND) { - char display_buf[128]; - - do { - getdata_str(4, 0, "½Ð³]©w¨B®É, ¥H¤ÀÄÁ¬°³æ¦ì:", - buf, 3, DOECHO, "5"); - _current_time_limit->limit_time = atoi(buf); - } while (_current_time_limit->limit_time < 0 || _current_time_limit->limit_time > 30); - _current_time_limit->limit_time *= 60; /* minute -> second */ - - snprintf(display_buf, sizeof(display_buf), - "½Ð³]©w¨B (¨C %d ¤ÀÄÁ»Ý¨«´X¨B):", - _current_time_limit->limit_time / 60); - do { - getdata_str(5, 0, display_buf, buf, 3, DOECHO, "10"); - _current_time_limit->limit_hand = atoi(buf); - } while (_current_time_limit->limit_hand < 1); - } else { - _current_time_limit->limit_hand = 1; - - do { - getdata_str(4, 0, "½Ð³]©wŪ¬í, ¥H¬í¬°³æ¦ì", - buf, 3, DOECHO, "60"); - _current_time_limit->limit_time = atoi(buf); - } while (_current_time_limit->limit_time < 0); - } - } else - _current_time_limit = NULL; - - my_talk(uin, friend_stat(currutmp, uin), func_char); - return 0; -} - -int -ChessWatchGame(void (*play)(int, ChessGameMode), int game, const char* title) -{ - int sock, msgsock; - userinfo_t *uin; - - if ((uin = ChessSearchUser(-1, title)) == NULL) - return -1; - - if (uin->uid == currutmp->uid || uin->mode != game) { - vmsg("µLªk«Ø¥ß³s½u"); - return -1; - } - - if (getans("¬O§_¶i¦æÆ[´Ñ? [N/y]") != 'y') - return 0; - - if ((sock = make_connection_to_somebody(uin, 10)) < 0) { - vmsg("µLªk«Ø¥ß³s½u"); - return -1; - } -#if defined(Solaris) && __OS_MAJOR_VERSION__ == 5 && __OS_MINOR_VERSION__ < 7 - msgsock = accept(sock, (struct sockaddr *) 0, 0); -#else - msgsock = accept(sock, (struct sockaddr *) 0, (socklen_t *) 0); -#endif - close(sock); - if (msgsock < 0) - return -1; - - strlcpy(currutmp->mateid, uin->userid, sizeof(currutmp->mateid)); - play(msgsock, CHESS_MODE_WATCH); - close(msgsock); - return 0; -} - -int -ChessReplayGame(const char* fname) -{ - ChessInfo *info; - FILE *fp = fopen(fname, "r"); - int found = -1; - char buf[256]; - screen_backup_t oldscreen; - - if(fp == NULL) { - vmsg("ÀÉ®×µLªk¶}±Ò, ¥i¯à³Q§R°£¤F"); - return -1; - } - - while (found == -1 && fgets(buf, sizeof(buf), fp)) { - if (buf[0] == '<') { - const int line_len = strlen(buf); - if (strcmp(buf + line_len - 5, "log>\n") == 0) { - int i; - for (i = 0; ChessReplayMap[i].name; ++i) - if (ChessReplayMap[i].name_len == line_len - 6 && - strncmp(buf + 1, ChessReplayMap[i].name, - ChessReplayMap[i].name_len) == 0) { - found = i; - break; - } - } - } - } - - if (found == -1) { - fclose(fp); - return -1; - } - - info = ChessReplayMap[found].func(fp); - fclose(fp); - - if (info) { - scr_dump(&oldscreen); - ChessPlay(info); - scr_restore(&oldscreen); - - DeleteChessInfo(info); - } - - return 0; -} - -static void -ChessInitUser(ChessInfo* info) -{ - char userid[2][IDLEN + 1]; - const userinfo_t* uinfo; - userec_t urec; - - switch (info->mode) { - case CHESS_MODE_PERSONAL: - strlcpy(userid[0], cuser.userid, sizeof(userid[0])); - strlcpy(userid[1], cuser.userid, sizeof(userid[1])); - break; - - case CHESS_MODE_WATCH: - uinfo = search_ulist_userid(currutmp->mateid); - if (uinfo) { - strlcpy(userid[0], uinfo->userid, sizeof(userid[0])); - strlcpy(userid[1], uinfo->mateid, sizeof(userid[1])); - } else { - strlcpy(userid[0], currutmp->mateid, sizeof(userid[0])); - userid[1][0] = 0; - } - break; - - case CHESS_MODE_VERSUS: - strlcpy(userid[0], cuser.userid, sizeof(userid[0])); - strlcpy(userid[1], currutmp->mateid, sizeof(userid[1])); - break; - - case CHESS_MODE_REPLAY: - return; - } - - uinfo = search_ulist_userid(userid[0]); - if (uinfo) - info->actions->init_user(uinfo, &info->user1); - else if (getuser(userid[0], &urec)) - info->actions->init_user_rec(&urec, &info->user1); - - uinfo = search_ulist_userid(userid[1]); - if (uinfo) - info->actions->init_user(uinfo, &info->user2); - else if (getuser(userid[1], &urec)) - info->actions->init_user_rec(&urec, &info->user2); -} - -#ifdef CHESSCOUNTRY -static char* -ChessPhotoInitial(ChessInfo* info) -{ - char genbuf[256]; - int line; - FILE* fp; - static const char * const blank_photo[6] = { - "¢z¢w¢w¢w¢w¢w¢w¢{", - "¢x ªÅ ¢x", - "¢x ¥Õ ¢x", - "¢x ·Ó ¢x", - "¢x ¤ù¢x", - "¢|¢w¢w¢w¢w¢w¢w¢}" - }; - char country[5], level[11]; - userec_t xuser; - char* photo; - int hasphoto = 0; - - if (info->mode == CHESS_MODE_REPLAY) - return NULL; - - if(is_validuserid(info->user1.userid)) { - sethomefile(genbuf, info->user1.userid, info->constants->photo_file_name); - if (dashf(genbuf)) - hasphoto++; - } - if(is_validuserid(info->user2.userid)) { - sethomefile(genbuf, info->user2.userid, info->constants->photo_file_name); - if (dashf(genbuf)) - hasphoto++; - } - if(hasphoto==0) - return NULL; - - photo = (char*) calloc( - CHESS_PHOTO_LINE * CHESS_PHOTO_COLUMN, sizeof(char)); - - /* simulate photo as two dimensional array */ -#define PHOTO(X) (photo + (X) * CHESS_PHOTO_COLUMN) - - fp = NULL; - if(getuser(info->user2.userid, &xuser)) { - sethomefile(genbuf, info->user2.userid, info->constants->photo_file_name); - fp = fopen(genbuf, "r"); - } - - if (fp == NULL) { - strcpy(country, "µL"); - level[0] = 0; - } else { - int i, j; - for (line = 1; line < 8; ++line) - fgets(genbuf, sizeof(genbuf), fp); - - fgets(genbuf, sizeof(genbuf), fp); - chomp(genbuf); - strip_ansi(genbuf + 11, genbuf + 11, - STRIP_ALL); /* country name may have color */ - for (i = 11, j = 0; genbuf[i] && j < 4; ++i) - if (genbuf[i] != ' ') /* and spaces */ - country[j++] = genbuf[i]; - country[j] = 0; /* two chinese words */ - - fgets(genbuf, sizeof(genbuf), fp); - chomp(genbuf); - strlcpy(level, genbuf + 11, 11); /* five chinese words*/ - rewind(fp); - } - - for (line = 0; line < 6; ++line) { - if (fp != NULL) { - if (fgets(genbuf, sizeof(genbuf), fp)) { - chomp(genbuf); - sprintf(PHOTO(line), "%s", genbuf); - } else - strcpy(PHOTO(line), " "); - } else - strcpy(PHOTO(line), blank_photo[line]); - - switch (line) { - case 0: sprintf(genbuf, " <¥N¸¹> %s", xuser.userid); break; - case 1: sprintf(genbuf, " <¼ÊºÙ> %.16s", xuser.nickname); break; - case 2: sprintf(genbuf, " <¤W¯¸> %d", xuser.numlogins); break; - case 3: sprintf(genbuf, " <¤å³¹> %d", xuser.numposts); break; - case 4: sprintf(genbuf, " <¾¦ì> %-4s %s", country, level); break; - case 5: sprintf(genbuf, " <¨Ó·½> %.16s", xuser.lasthost); break; - default: genbuf[0] = 0; - } - strcat(PHOTO(line), genbuf); - } - if (fp != NULL) - fclose(fp); - - sprintf(PHOTO(6), " %s%2.2s´Ñ" ANSI_RESET, - info->constants->turn_color[(int) info->myturn ^ 1], - info->constants->turn_str[(int) info->myturn ^ 1]); - strcpy(PHOTO(7), " ¢ä.¢á "); - sprintf(PHOTO(8), " %s%2.2s´Ñ" ANSI_RESET, - info->constants->turn_color[(int) info->myturn], - info->constants->turn_str[(int) info->myturn]); - - fp = NULL; - if(getuser(info->user1.userid, &xuser)) {; - sethomefile(genbuf, info->user1.userid, info->constants->photo_file_name); - fp = fopen(genbuf, "r"); - } - - if (fp == NULL) { - strcpy(country, "µL"); - level[0] = 0; - } else { - int i, j; - for (line = 1; line < 8; ++line) - fgets(genbuf, sizeof(genbuf), fp); - - fgets(genbuf, sizeof(genbuf), fp); - chomp(genbuf); - strip_ansi(genbuf + 11, genbuf + 11, - STRIP_ALL); /* country name may have color */ - for (i = 11, j = 0; genbuf[i] && j < 4; ++i) - if (genbuf[i] != ' ') /* and spaces */ - country[j++] = genbuf[i]; - country[j] = 0; /* two chinese words */ - - fgets(genbuf, sizeof(genbuf), fp); - chomp(genbuf); - strlcpy(level, genbuf + 11, 11); /* five chinese words*/ - rewind(fp); - } - - for (line = 9; line < 15; ++line) { - move(line, 37); - switch (line - 9) { - case 0: sprintf(PHOTO(line), "<¥N¸¹> %-16.16s ", xuser.userid); break; - case 1: sprintf(PHOTO(line), "<¼ÊºÙ> %-16.16s ", xuser.nickname); break; - case 2: sprintf(PHOTO(line), "<¤W¯¸> %-16d ", xuser.numlogins); break; - case 3: sprintf(PHOTO(line), "<¤å³¹> %-16d ", xuser.numposts); break; - case 4: sprintf(PHOTO(line), "<¾¦ì> %-4s %-10s ", country, level); break; - case 5: sprintf(PHOTO(line), "<¨Ó·½> %-16.16s ", xuser.lasthost); break; - } - - if (fp != NULL) { - if (fgets(genbuf, 200, fp)) { - chomp(genbuf); - strcat(PHOTO(line), genbuf); - } else - strcat(PHOTO(line), " "); - } else - strcat(PHOTO(line), blank_photo[line - 9]); - } - if (fp != NULL) - fclose(fp); -#undef PHOTO - - return photo; -} -#endif /* defined(CHESSCOUNTRY) */ - -static void -ChessInitPlayFunc(ChessInfo* info) -{ - switch (info->mode) { - case CHESS_MODE_VERSUS: - info->play_func[(int) info->myturn] = &ChessPlayFuncMy; - info->play_func[info->myturn ^ 1] = &ChessPlayFuncHis; - break; - - case CHESS_MODE_WATCH: - case CHESS_MODE_REPLAY: - info->play_func[0] = info->play_func[1] = &ChessPlayFuncWatch; - break; - - case CHESS_MODE_PERSONAL: - info->play_func[0] = info->play_func[1] = &ChessPlayFuncMy; - break; - } -} - -ChessInfo* -NewChessInfo(const ChessActions* actions, const ChessConstants* constants, - int sock, ChessGameMode mode) -{ - /* allocate memory for the structure and extra space for temporary - * steping information storage (step_tmp[0]). */ - ChessInfo* info = - (ChessInfo*) calloc(1, sizeof(ChessInfo) + constants->step_entry_size); - - if (mode == CHESS_MODE_PERSONAL) - strcpy(currutmp->mateid, cuser.userid); - - /* compiler don't know it's actually const... */ - info->actions = (ChessActions*) actions; - info->constants = (ChessConstants*) constants; - info->mode = mode; - info->sock = sock; - - if (mode == CHESS_MODE_VERSUS) - info->myturn = currutmp->turn; - else if (mode == CHESS_MODE_PERSONAL) - info->myturn = 1; - else if (mode == CHESS_MODE_REPLAY) - info->myturn = 1; - else if (mode == CHESS_MODE_WATCH) - ChessReceiveWatchInfo(info); - - ChessInitUser(info); - -#ifdef CHESSCOUNTRY - info->photo = ChessPhotoInitial(info); -#endif - - if (mode != CHESS_MODE_WATCH) - ChessHistoryInit(&info->history, constants->step_entry_size); - - ChessBroadcastListInit(&info->broadcast_list); - ChessInitPlayFunc(info); - - return info; -} - -void -DeleteChessInfo(ChessInfo* info) -{ -#define NULL_OR_FREE(X) if (X) free(X); else (void) 0 - NULL_OR_FREE(info->timelimit); - NULL_OR_FREE(info->photo); - NULL_OR_FREE(info->history.body); - - ChessBroadcastListClear(&info->broadcast_list); -#undef NULL_OR_FREE -} - -void -ChessEstablishRequest(int sock) -{ - /* XXX */ - if (!_current_time_limit) - write(sock, "T", 1); /* traditional */ - else { - write(sock, "L", 1); /* limited */ - write(sock, _current_time_limit, sizeof(ChessTimeLimit)); - } -} - -void -ChessAcceptingRequest(int sock) -{ - /* XXX */ - char mode; - read(sock, &mode, 1); - if (mode == 'T') - _current_time_limit = NULL; - else { - _current_time_limit = (ChessTimeLimit*) malloc(sizeof(ChessTimeLimit)); - read(sock, _current_time_limit, sizeof(ChessTimeLimit)); - } -} - -void -ChessShowRequest(void) -{ - /* XXX */ - if (!_current_time_limit) - mouts(10, 5, "¨Ï¥Î¶Ç²Îp®É¤è¦¡, ³æ¨B®É¤¤ÀÄÁ"); - else if (_current_time_limit->time_mode == CHESS_TIMEMODE_MULTIHAND) { - mouts(10, 5, "¨Ï¥Î®É¨B³W«h:"); - move(12, 8); - prints("§½®É (¦Û¥Ñ®É¶¡): %2d ¤À %02d ¬í", - _current_time_limit->free_time / 60, - _current_time_limit->free_time % 60); - move(13, 8); - prints("®É¨B®É: %2d ¤À %02d ¬í / %2d ¤â", - _current_time_limit->limit_time / 60, - _current_time_limit->limit_time % 60, - _current_time_limit->limit_hand); - } else if (_current_time_limit->time_mode == CHESS_TIMEMODE_COUNTING) { - mouts(10, 5, "¨Ï¥ÎŪ¬í³W«h:"); - move(12, 8); - prints("§½®É (¦Û¥Ñ®É¶¡): %2d ¤À %02d ¬í", - _current_time_limit->free_time / 60, - _current_time_limit->free_time % 60); - move(13, 8); - prints("Ū¬í®É¶¡: ¨C¤â %2d ¬í", _current_time_limit->limit_time); - } -} - -inline static const char* -ChessTimeStr(int second) -{ - static char buf[10]; - snprintf(buf, sizeof(buf), "%d:%02d", second / 60, second % 60); - return buf; -} - -void -ChessDrawExtraInfo(const ChessInfo* info, int line, int space) -{ - if (line == b_lines || line == 0) - return; - - if (info->photo) { - if (line >= 3 && line < 3 + CHESS_PHOTO_LINE) { - if (space > 3) - outs(" "); - outs(info->photo + (line - 3) * CHESS_PHOTO_COLUMN); - } else if (line >= CHESS_DRAWING_PHOTOED_STEP_ROW && - line <= CHESS_DRAWING_PHOTOED_WARN_ROW) { - prints("%*s", space, ""); - if (line == CHESS_DRAWING_PHOTOED_STEP_ROW) - outs(info->last_movestr); - else if (line == CHESS_DRAWING_PHOTOED_TURN_ROW) - prints(ANSI_COLOR(1;33) "%s" ANSI_RESET, - info->myturn == info->turn ? "½ü¨ì§A¤U´Ñ¤F" : "µ¥«Ý¹ï¤è¤U´Ñ"); - else if (line == CHESS_DRAWING_PHOTOED_TIME_ROW1) { - if (info->mode == CHESS_MODE_WATCH) { - if (!info->timelimit) - prints("¨C¤â®É¤¤ÀÄÁ"); - else - prints("§½®É: %5s", - ChessTimeStr(info->timelimit->free_time)); - } else if (info->lefthand[0]) - prints("§Ú¤è³Ñ¾l®É¶¡ %s / %2d ¨B", - ChessTimeStr(info->lefttime[0]), - info->lefthand[0]); - else - prints("§Ú¤è³Ñ¾l®É¶¡ %s", - ChessTimeStr(info->lefttime[0])); - } else if (line == CHESS_DRAWING_PHOTOED_TIME_ROW2) { - if (info->mode == CHESS_MODE_WATCH) { - if (info->timelimit) { - if (info->timelimit->time_mode == - CHESS_TIMEMODE_MULTIHAND) - prints("¨B®É: %s / %2d ¨B", - ChessTimeStr(info->timelimit->limit_time), - info->timelimit->limit_hand); - else - prints("Ū¬í: %5d ¬í", - info->timelimit->limit_time); - } - } else if (info->lefthand[1]) - prints("¹ï¤è³Ñ¾l®É¶¡ %s / %2d ¨B", - ChessTimeStr(info->lefttime[1]), - info->lefthand[1]); - else - prints("¹ï¤è³Ñ¾l®É¶¡ %s", - ChessTimeStr(info->lefttime[1])); - } else if (line == CHESS_DRAWING_PHOTOED_WARN_ROW) - outs(info->warnmsg); - } - } else if (line >= 3 && line <= CHESS_DRAWING_HISWIN_ROW) { - prints("%*s", space, ""); - if (line >= 3 && line < 3 + (int)dim(ChessHintStr)) { - outs(ChessHintStr[line - 3]); - } else if (line == CHESS_DRAWING_SIDE_ROW) { - prints(ANSI_COLOR(1) "§A¬O%s%s" ANSI_RESET, - info->constants->turn_color[(int) info->myturn], - info->constants->turn_str[(int) info->myturn]); - } else if (line == CHESS_DRAWING_REAL_TURN_ROW) { - prints(ANSI_COLOR(1;33) "%s" ANSI_RESET, - info->myturn == info->turn ? - "½ü¨ì§A¤U´Ñ¤F" : "µ¥«Ý¹ï¤è¤U´Ñ"); - } else if (line == CHESS_DRAWING_REAL_STEP_ROW && info->last_movestr) { - outs(info->last_movestr); - } else if (line == CHESS_DRAWING_REAL_TIME_ROW1) { - if (info->lefthand[0]) - prints("§Ú¤è³Ñ¾l®É¶¡ %s / %2d ¨B", - ChessTimeStr(info->lefttime[0]), - info->lefthand[0]); - else - prints("§Ú¤è³Ñ¾l®É¶¡ %s", - ChessTimeStr(info->lefttime[0])); - } else if (line == CHESS_DRAWING_REAL_TIME_ROW2) { - if (info->lefthand[1]) - prints("¹ï¤è³Ñ¾l®É¶¡ %s / %2d ¨B", - ChessTimeStr(info->lefttime[1]), - info->lefthand[1]); - else - prints("¹ï¤è³Ñ¾l®É¶¡ %s", - ChessTimeStr(info->lefttime[1])); - } else if (line == CHESS_DRAWING_REAL_WARN_ROW) { - outs(info->warnmsg); - } else if (line == CHESS_DRAWING_MYWIN_ROW) { - prints(ANSI_COLOR(1;33) "%12.12s " - ANSI_COLOR(1;31) "%2d" ANSI_COLOR(37) "³Ó " - ANSI_COLOR(34) "%2d" ANSI_COLOR(37) "±Ñ " - ANSI_COLOR(36) "%2d" ANSI_COLOR(37) "©M" ANSI_RESET, - info->user1.userid, - info->user1.win, info->user1.lose - 1, info->user1.tie); - } else if (line == CHESS_DRAWING_HISWIN_ROW) { - prints(ANSI_COLOR(1;33) "%12.12s " - ANSI_COLOR(1;31) "%2d" ANSI_COLOR(37) "³Ó " - ANSI_COLOR(34) "%2d" ANSI_COLOR(37) "±Ñ " - ANSI_COLOR(36) "%2d" ANSI_COLOR(37) "©M" ANSI_RESET, - info->user2.userid, - info->user2.win, info->user2.lose, info->user2.tie); - } - } -} diff --git a/mbbsd/chicken.c b/mbbsd/chicken.c deleted file mode 100644 index 4de2bb85..00000000 --- a/mbbsd/chicken.c +++ /dev/null @@ -1,1138 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -// TODO pull chicken out of userec. -// remove chickenpk. - -#define NUM_KINDS 15 /* ¦³¦h¤ÖºØ°Êª« */ -#define CHICKENLOG "etc/chicken" - -// enable if you want to run live upgrade -// #define CHICKEN_LIVE_UPGRADE - -static const char * const cage[17] = { - "½Ï¥Í", "¶g·³", "¥®¦~", "¤Ö¦~", "«C¬K", "«C¦~", - "«C¦~", "¬¡¤O", "§§¦~", "§§¦~", "§§¦~", "¤¤¦~", - "¤¤¦~", "¦Ñ¦~", "¦Ñ¦~", "¦Ñáàáà", "¥j§Æ"}; -static const char * const chicken_type[NUM_KINDS] = { - "¤pÂû", "¬ü¤Ö¤k", "«i¤h", "»jµï", - "®£Às", "¦ÑÆN", "¿ß", "Äúµ§¤p·s", - "ª¯ª¯", "´cÅ]", "§ÔªÌ", "£««ó", - "°¨^¤E", "´N¥i¤H", "ÅÚ²ú"}; -static const char * const chicken_food[NUM_KINDS] = { - "Âû¹}®Æ", "Àç¾i«p¤ù", "Âû±Æ«K·í", "¦º½¹½º", - "«ÍÅé", "¤pÂû", "¿ß»æ°®", "¤pºµ»æ°®", - "Ä_¿ý", "ÆF®ð", "¶º¹Î", "«K·í", - "Âû»L", "¯º¸Ü¤å³¹", "¤ôªG¨F©Ô"}; -static const int egg_price[NUM_KINDS] = { - 5, 25, 30, 40, - 80, 50, 15, 35, - 17, 100, 85, 200, - 200, 100, 77}; -static const int food_price[NUM_KINDS] = { - 4, 6, 8, 10, - 12, 12, 5, 6, - 5, 20, 15, 23, - 23, 10, 19}; -static const char * const attack_type[NUM_KINDS] = { - "°Ö", "Ã@¥´", "ºl", "«r", - "¼²À»", "°Ö", "§ì", "½ð", - "«r", "¿U¿N", "·tÀ»", "´Ò¥´", - "¼CÀ»", "§Ná¥ú½u", "»§k¤@ªT"}; - -static const char * const damage_degree[] = { - "°A¤l¦üªº", "ÄÌÄo¦üªº", "¤p¤Oªº", "»´·Lªº", - "¦³ÂI¯kªº", "¨Ï¤Oªº", "¶Ë¤Hªº", "««ªº", - "¨Ï¥þ¤Oªº", "´c¬½¬½ªº", "¦MÀIªº", "ºÆ¨gªº", - "²r¯Pªº", "¨g·¼É«B¦üªº", "Åå¤Ñ°Ê¦aªº", - "P©Rªº", NULL}; - -enum { - OO, FOOD, WEIGHT, CLEAN, RUN, ATTACK, BOOK, HAPPY, SATIS, - TEMPERAMENT, TIREDSTRONG, SICK, HP_MAX, MM_MAX -}; - -static const short time_change[NUM_KINDS][14] = -/* ¸É«~ ¹ª« Åé« °®²b ±Ó±¶ §ðÀ»¤O ª¾ÃÑ §Ö¼Ö º¡·N ®ð½è ¯h³Ò ¯f®ð º¡¦å º¡ªk */ -{ - /* Âû */ - {1, 1, 30, 3, 8, 3, 3, 40, 9, 1, 7, 3, 30, 1}, - /* ¬ü¤Ö¤k */ - {1, 1, 110, 1, 4, 7, 41, 20, 9, 25, 25, 7, 110, 15}, - /* «i¤h */ - {1, 1, 200, 5, 4, 10, 33, 20, 15, 10, 27, 1, 200, 9}, - /* »jµï */ - {1, 1, 10, 5, 8, 1, 1, 5, 3, 1, 4, 1, 10, 30}, - /* ®£Às */ - {1, 1, 1000, 9, 1, 13, 4, 12, 3, 1, 200, 1, 1000, 3}, - /* ¦ÑÆN */ - {1, 1, 90, 7, 10, 7, 4, 12, 3, 30, 20, 5, 90, 20}, - /* ¿ß */ - {1, 1, 30, 5, 5, 6, 4, 8, 3, 15, 7, 4, 30, 21}, - /* Äúµ§¤p·s */ - {1, 1, 100, 9, 7, 7, 20, 50, 10, 8, 24, 4, 100, 9}, - /* ª¯ */ - {1, 1, 45, 8, 7, 9, 3, 40, 20, 3, 9, 5, 45, 1}, - /* ´cÅ] */ - {1, 1, 45, 10, 11, 11, 5, 21, 11, 1, 9, 5, 45, 25}, - /* §ÔªÌ */ - {1, 1, 45, 2, 12, 10, 25, 1, 1, 10, 9, 5, 45, 26}, - /* ªü«ó */ - {1, 1, 150, 4, 8, 13, 95, 25, 7, 10, 25, 5, 175, 85}, - /* °¨^¤E */ - {1, 1, 147, 2, 10, 10, 85, 20, 4, 25, 25, 5, 145, 95}, - /* ´N¥i¤H */ - {1, 1, 200, 3, 15, 15, 50, 50, 10, 5, 10, 2, 300, 0}, - /* ù§Q */ - {1, 1, 80, 2, 9, 10, 2, 5, 7, 8, 12, 1, 135, 5}, -}; - -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) -{ - 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; -} - -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; -} - -void free_live_chicken(chicken_t *p) -{ - if (!p) return; - munmap(p, sizeof(chicken_t)); -} - -void -chicken_query(const char *userid) -{ - chicken_t xchicken; - -#ifdef CHICKEN_LIVE_UPGRADE - // live update - vmsg("PTT ¨t²Î¶i¦æ§ó·s¡A¥»¶g¼È°±¶}©ñÃdª«¬d¸ß¡C"); - return; -#endif - - if (!load_chicken(userid, &xchicken)) - { - move(1, 0); - clrtobot(); - prints("\n\n%s ¨Ã¨S¦³¾iÃdª«..", userid); - } else { - time_diff(&xchicken); - if (!isdeadth(&xchicken, NULL)) - { - show_chicken_data(&xchicken, NULL); - prints("\n\n¥H¤W¬O %s ªºÃdª«¸ê®Æ..", userid); - } else { - move(1, 0); - clrtobot(); - prints("\n\n%s ªºÃdª«¦º±¼¤F...", userid); - } - } - - pressanykey(); -} - -static int -new_chicken(void) -{ - chicken_t mychicken; - int price, i; - int fd; - char fn[PATHLEN]; - - memset(&mychicken, 0, sizeof(chicken_t)); - - clear(); - move(2, 0); - outs("Åwªï¥úÁ{ " ANSI_COLOR(33) "¡·" ANSI_COLOR(37;44) " " - BBSMNAME "Ãdª«¥«³õ " ANSI_COLOR(33;40) "¡·" ANSI_RESET ".. " - "¥Ø«e³J»ù¡G\n" - "(a)¤pÂû $5 (b)¬ü¤Ö¤k $25 (c)«i¤h $30 (d)»jµï $40 " - "(e)®£Às $80\n" - "(f)¦ÑÆN $50 (g)¿ß $15 (h)Äúµ§¤p·s$35 (i)ª¯ª¯ $17 " - "(j)´cÅ] $100\n" - "(k)§ÔªÌ $85 (n)´N¥i¤H$100 (m)ÅÚ²ú $77\n" - "[0]¤£·Q¶R¤F $0\n"); - i = getans("½Ð¿ï¾Ü§An¾iªº°Êª«¡G"); - - // since (o) is confusing to some people, we alias 'm' to 'o'. - if (i == 'm') i = 'o'; - - // (m, l) were political person. - // do not make them in a BBS system... - if (i == 'm' || i == 'l') - return 0; - - i -= 'a'; - if (i < 0 || i > NUM_KINDS - 1) - return 0; - - mychicken.type = i; - - price = egg_price[(int)mychicken.type]; - reload_money(); - if (cuser.money < price) { - vmsgf("¿ú¤£°÷¶R³J³J,³J³Jn %d ¤¸", price); - return 0; - } - - while (strlen(mychicken.name) < 3) - { - getdata(8, 0, "À°¨e¨úÓ¦n¦W¦r¡G", 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; - - reload_money(); - if (cuser.money < price) - { - vmsg("¿ú¤£°÷¤F¡C"); - return 0; - } - vice(price, "Ãdª«³J"); - - // flush it - setuserfile(fn, FN_CHICKEN); - fd = open(fn, O_WRONLY|O_CREAT, 0666); - if (fd < 0) - { - vmsg("¨t²Î¿ù»~: µLªk«Ø¥ß¸ê®Æ¡A½Ð¦Ü " GLOBAL_BUGREPORT " ³ø§i¡C"); - return 0; - } - - write(fd, &mychicken, sizeof(chicken_t)); - close(fd); - - // log data - log_filef(CHICKENLOG, LOG_CREAT, - ANSI_COLOR(31) "%s " ANSI_RESET "¾i¤F¤@°¦¥s" 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)); - return 1; -} - -static void -show_chicken_stat(const chicken_t * thechicken, int age) -{ - struct tm *ptime; - - ptime = localtime4(&thechicken->birthday); - prints(" Name :" ANSI_COLOR(33) "%s" ANSI_RESET " (" ANSI_COLOR(32) "%s" ANSI_RESET ")%*s¥Í¤é " - ":" ANSI_COLOR(31) "%02d" ANSI_RESET "¦~" ANSI_COLOR(31) "%2d" ANSI_RESET "¤ë" ANSI_COLOR(31) "%2d" ANSI_RESET "¤é " - "(" ANSI_COLOR(32) "%s %d·³" ANSI_RESET ")\n" - " Åé:" ANSI_COLOR(33) "%5d/%-5d" ANSI_RESET " ªk:" ANSI_COLOR(33) "%5d/%-5d" ANSI_RESET " §ðÀ»¤O:" - 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 " º¡·N :" ANSI_COLOR(33) "%-7d " ANSI_RESET " ¯h³Ò :" - ANSI_COLOR(33) "%-7d" ANSI_RESET " ®ð½è :" ANSI_COLOR(33) "%-7d " ANSI_RESET "Åé« :" - ANSI_COLOR(33) "%-5.2f" ANSI_RESET " \n" - " ¯f®ð :" ANSI_COLOR(33) "%-7d " ANSI_RESET " °®²b :" ANSI_COLOR(33) "%-7d " ANSI_RESET " ¹ª« :" - ANSI_COLOR(33) "%-7d" ANSI_RESET " ¤j¸É¤Y:" ANSI_COLOR(33) "%-7d" ANSI_RESET " ÃÄ«~ :" ANSI_COLOR(33) "%-7d" - ANSI_RESET " \n", - thechicken->name, chicken_type[(int)thechicken->type], - strlen(thechicken->name) >= 15 ? 0 : (int)(15 - strlen(thechicken->name)), "", - ptime->tm_year % 100, ptime->tm_mon + 1, ptime->tm_mday, - cage[age > 16 ? 16 : age], age, thechicken->hp, thechicken->hp_max, - thechicken->mm, thechicken->mm_max, - thechicken->attack, thechicken->run, thechicken->book, - thechicken->happy, thechicken->satis, thechicken->tiredstrong, - thechicken->temperament, - ((float)(thechicken->hp_max + (thechicken->weight / 50))) / 100, - thechicken->sick, thechicken->clean, thechicken->food, - thechicken->oo, thechicken->medicine); -} - -#define CHICKEN_PIC "etc/chickens" - -static void -show_chicken_picture(const char *fpath) -{ - show_file(fpath, 5, 14, SHOWFILE_ALLOW_ALL); -} - -void -show_chicken_data(chicken_t * thechicken, chicken_t * pkchicken) -{ - char buf[1024]; - int age = ((now - thechicken->cbirth) / (60 * 60 * 24)); - if (age < 0) { - thechicken->birthday = thechicken->cbirth = now - 10 * (60 * 60 * 24); - age = 10; - } - /* Ptt:debug */ - thechicken->type %= NUM_KINDS; - clear(); - showtitle(pkchicken ? BBSMNAME2 "°«Âû³õ" : BBSMNAME2 "¾iÂû³õ", BBSName); - move(1, 0); - - show_chicken_stat(thechicken, age); - - snprintf(buf, sizeof(buf), CHICKEN_PIC "/%c%d", thechicken->type + 'a', - age > 16 ? 16 : age); - - show_chicken_picture(buf); - - move(18, 0); - - if (thechicken->sick) - outs("¥Í¯f¤F..."); - if (thechicken->sick > thechicken->hp / 5) - outs(ANSI_COLOR(5;31) "¾á¤ß...¯f«!!" ANSI_RESET); - - if (thechicken->clean > 150) - outs(ANSI_COLOR(31) "¤S¯ä¤Sżªº.." ANSI_RESET); - else if (thechicken->clean > 80) - outs("¦³ÂIż.."); - else if (thechicken->clean < 20) - outs(ANSI_COLOR(32) "«Ü°®²b.." ANSI_RESET); - - if (thechicken->weight > thechicken->hp_max * 4) - outs(ANSI_COLOR(31) "§Ö¹¡¦º¤F!." ANSI_RESET); - else if (thechicken->weight > thechicken->hp_max * 3) - outs(ANSI_COLOR(32) "¹¡¹Ê¹Ê.." ANSI_RESET); - else if (thechicken->weight < (thechicken->hp_max / 4)) - outs(ANSI_COLOR(31) "§Ö¾j¦º¤F!.." ANSI_RESET); - else if (thechicken->weight < (thechicken->hp_max / 2)) - outs("¾j¤F.."); - - if (thechicken->tiredstrong > thechicken->hp * 1.7) - outs(ANSI_COLOR(31) "²Ö±o©ü°g¤F..." ANSI_RESET); - else if (thechicken->tiredstrong > thechicken->hp) - outs("²Ö¤F.."); - else if (thechicken->tiredstrong < thechicken->hp / 4) - outs(ANSI_COLOR(32) "ºë¤O©ô²±..." ANSI_RESET); - - if (thechicken->hp < thechicken->hp_max / 4) - outs(ANSI_COLOR(31) "Åé¤O¥ÎºÉ..©a©a¤@®§.." ANSI_RESET); - if (thechicken->happy > 500) - outs(ANSI_COLOR(32) "«Ü§Ö¼Ö.." ANSI_RESET); - else if (thechicken->happy < 100) - outs("¤£§Ö¼Ö.."); - if (thechicken->satis > 500) - outs(ANSI_COLOR(32) "«Üº¡¨¬.." ANSI_RESET); - else if (thechicken->satis < 50) - outs("¤£º¡¨¬.."); - - if (pkchicken) { - outc('\n'); - show_chicken_stat(pkchicken, age); - outs("[¥ô·NÁä] §ðÀ»¹ï¤è [q] ¸¨¶] [o] ¦Y¤j¸É¤Y"); - } -} - -static void -ch_eat(chicken_t *mychicken) -{ - if (mychicken->food) { - mychicken->weight += time_change[(int)mychicken->type][WEIGHT] + - mychicken->hp_max / 5; - mychicken->tiredstrong += - time_change[(int)mychicken->type][TIREDSTRONG] / 2; - mychicken->hp_max++; - mychicken->happy += 5; - mychicken->satis += 7; - mychicken->food--; - move(10, 10); - - show_chicken_picture(CHICKEN_PIC "/eat"); - pressanykey(); - } -} - -static void -ch_clean(chicken_t *mychicken) -{ - mychicken->clean = 0; - mychicken->tiredstrong += - time_change[(int)mychicken->type][TIREDSTRONG] / 3; - show_chicken_picture(CHICKEN_PIC "/clean"); - pressanykey(); -} - -static void -ch_guess(chicken_t *mychicken) -{ - char *guess[3] = {"°Å¤M", "¥ÛÀY", "¥¬"}, me, ch, win; - - 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]; - mychicken->attack += time_change[(int)mychicken->type][ATTACK] / 4; - move(20, 0); - clrtobot(); - outs("§An¥X[" ANSI_COLOR(32) "1" ANSI_RESET "]" ANSI_COLOR(33) "°Å¤M" ANSI_RESET "(" ANSI_COLOR(32) "2" ANSI_RESET ")" - ANSI_COLOR(33) "¥ÛÀY" ANSI_RESET "(" ANSI_COLOR(32) "3" ANSI_RESET ")" ANSI_COLOR(33) "¥¬" ANSI_RESET ":\n"); - me = igetch(); - me -= '1'; - if (me > 2 || me < 0) - me = 0; - win = (int)(3.0 * random() / (RAND_MAX + 1.0)) - 1; - ch = (me + win + 3) % 3; - prints("%s:%s ! %s:%s !.....%s", - cuser.userid, guess[(int)me], mychicken->name, guess[(int)ch], - win == 0 ? "¥¤â" : win < 0 ? "C..ŤF :D!!" : "¶ã..§Ú¿é¤F :~"); - pressanykey(); -} - -static void -ch_book(chicken_t *mychicken) -{ - mychicken->book += time_change[(int)mychicken->type][BOOK]; - mychicken->tiredstrong += time_change[(int)mychicken->type][TIREDSTRONG]; - show_chicken_picture(CHICKEN_PIC "/read"); - pressanykey(); -} - -static void -ch_kiss(chicken_t *mychicken) -{ - mychicken->happy += time_change[(int)mychicken->type][HAPPY]; - mychicken->satis += time_change[(int)mychicken->type][SATIS]; - mychicken->tiredstrong += - time_change[(int)mychicken->type][TIREDSTRONG] / 2; - show_chicken_picture(CHICKEN_PIC "/kiss"); - pressanykey(); -} - -static void -ch_hit(chicken_t *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; - mychicken->weight -= mychicken->hp_max / 15; - mychicken->hp -= (int)((float)time_change[(int)mychicken->type][HP_MAX] * - random() / (RAND_MAX + 1.0)) / 2 + 1; - - if (mychicken->book > 2) - mychicken->book -= 2; - if (mychicken->happy > 2) - mychicken->happy -= 2; - if (mychicken->satis > 2) - mychicken->satis -= 2; - mychicken->tiredstrong += time_change[(int)mychicken->type][TIREDSTRONG]; - show_chicken_picture(CHICKEN_PIC "/hit"); - pressanykey(); -} - -void -ch_buyitem(int money, const char *picture, int *item, int haveticket) -{ - int num = 0; - char buf[5]; - - getdata_str(b_lines - 1, 0, "n¶R¦h¤Ö¥÷©O:", - buf, sizeof(buf), DOECHO, "1"); - num = atoi(buf); - if (num < 1) - return; - reload_money(); - if (cuser.money/money >= num) { - *item += num; - if( haveticket ) - vice(money * num, "ÁʶRÃdª«,½ä½L¶µ¥Ø"); - else - demoney(-money * num); - show_chicken_picture(picture); - pressanykey(); - } else { - vmsg("²{ª÷¤£°÷ !!!"); - } - usleep(100000); // sleep 0.1s -} - -static void -ch_eatoo(chicken_t *mychicken) -{ - if (mychicken->oo > 0) { - mychicken->oo--; - mychicken->tiredstrong = 0; - if (mychicken->happy > 5) - mychicken->happy -= 5; - show_chicken_picture(CHICKEN_PIC "/oo"); - pressanykey(); - } -} - -static void -ch_eatmedicine(chicken_t *mychicken) -{ - if (mychicken->medicine > 0) { - mychicken->medicine--; - mychicken->sick = 0; - if (mychicken->hp_max > 10) - mychicken->hp_max -= 3; - mychicken->hp = mychicken->hp_max; - if (mychicken->happy > 10) - mychicken->happy -= 10; - show_chicken_picture(CHICKEN_PIC "/medicine"); - pressanykey(); - } -} - -static void -ch_kill(chicken_t *mychicken) -{ - int ans; - - ans = getans("±ó¾in³Q»@ 100 ¤¸, ¬O§_n±ó¾i?(y/N)"); - if (ans == 'y') { - - vice(100, "±ó¾iÃdª«¶O"); - more(CHICKEN_PIC "/deadth", YEA); - log_filef(CHICKENLOG, LOG_CREAT, - ANSI_COLOR(31) "%s " ANSI_RESET "§â " ANSI_COLOR(33) "%s" ANSI_RESET ANSI_COLOR(32) " %s " - ANSI_RESET "®_¤F ©ó %s\n", cuser.userid, mychicken->name, - chicken_type[(int)mychicken->type], ctime4(&now)); - mychicken->name[0] = 0; - } -} - -static void -geting_old(int *hp, int *weight, int diff, int age) -{ - float ex = 0.9; - - if (age > 70) - ex = 0.1; - else if (age > 30) - ex = 0.5; - else if (age > 20) - ex = 0.7; - - diff /= 60 * 6; - while (diff--) { - *hp *= ex; - *weight *= ex; - } -} - -/* ¨Ì®É¶¡Åܰʪº¸ê®Æ */ -static void -time_diff(chicken_t * thechicken) -{ - int diff; - int theage = ((now - thechicken->cbirth) / (60 * 60 * 24)); - - thechicken->type %= NUM_KINDS; - diff = (now - thechicken->lastvisit) / 60; - - if ((diff) < 1) - return; - - if (theage > 13) /* ¦Ñ¦º */ - geting_old(&thechicken->hp_max, &thechicken->weight, diff, theage); - - thechicken->lastvisit = now; - thechicken->weight -= thechicken->hp_max * diff / 540; /* Åé« */ - if (thechicken->weight < 1) { - thechicken->sick -= thechicken->weight / 10; /* ¾j±o¯f®ð¤W¤É */ - thechicken->weight = 1; - } - /* ²M¼ä«× */ - thechicken->clean += diff * time_change[(int)thechicken->type][CLEAN] / 30; - - /* §Ö¼Ö«× */ - thechicken->happy -= diff / 60; - if (thechicken->happy < 0) - thechicken->happy = 0; - thechicken->attack -= - time_change[(int)thechicken->type][ATTACK] * diff / (60 * 32); - if (thechicken->attack < 0) - thechicken->attack = 0; - /* §ðÀ»¤O */ - thechicken->run -= time_change[(int)thechicken->type][RUN] * diff / (60 * 32); - /* ±Ó±¶ */ - if (thechicken->run < 0) - thechicken->run = 0; - thechicken->book -= time_change[(int)thechicken->type][BOOK] * diff / (60 * 32); - /* ª¾ÃÑ */ - if (thechicken->book < 0) - thechicken->book = 0; - /* ®ð½è */ - thechicken->temperament++; - - thechicken->satis -= diff / 60 / 3 * time_change[(int)thechicken->type][SATIS]; - /* º¡·N«× */ - if (thechicken->satis < 0) - thechicken->satis = 0; - - /* ż¯fªº */ - if (thechicken->clean > 1000) - thechicken->sick += (thechicken->clean - 400) / 10; - - if (thechicken->weight > 1) - thechicken->sick -= diff / 60; - /* ¯f®ð«ìÅ@ */ - if (thechicken->sick < 0) - thechicken->sick = 0; - thechicken->tiredstrong -= diff * - time_change[(int)thechicken->type][TIREDSTRONG] / 4; - /* ¯h³Ò */ - if (thechicken->tiredstrong < 0) - thechicken->tiredstrong = 0; - /* hp_max */ - if (thechicken->hp >= thechicken->hp_max / 2) - thechicken->hp_max += - time_change[(int)thechicken->type][HP_MAX] * diff / (60 * 12); - /* hp«ìÅ@ */ - if (!thechicken->sick) - thechicken->hp += - time_change[(int)thechicken->type][HP_MAX] * diff / (60 * 6); - if (thechicken->hp > thechicken->hp_max) - thechicken->hp = thechicken->hp_max; - /* mm_max */ - if (thechicken->mm >= thechicken->mm_max / 2) - thechicken->mm_max += - time_change[(int)thechicken->type][MM_MAX] * diff / (60 * 8); - /* mm«ìÅ@ */ - if (!thechicken->sick) - thechicken->mm += diff; - if (thechicken->mm > thechicken->mm_max) - thechicken->mm = thechicken->mm_max; -} - -static void -check_sick(chicken_t *mychicken) -{ - /* ż¯fªº */ - if (mychicken->tiredstrong > mychicken->hp * 0.3 && mychicken->clean > 150) - mychicken->sick += (mychicken->clean - 150) / 10; - /* ²Ö¯fªº */ - if (mychicken->tiredstrong > mychicken->hp * 1.3) - mychicken->sick += time_change[(int)mychicken->type][SICK]; - /* ¯f®ð¤Ó«ÁÙ°µ¨Æ´îhp */ - if (mychicken->sick > mychicken->hp / 5) { - mychicken->hp -= (mychicken->sick - mychicken->hp / 5) / 4; - if (mychicken->hp < 0) - mychicken->hp = 0; - } -} - -static int -deadtype(const chicken_t * thechicken, chicken_t *mychicken) -{ - int i; - - if (thechicken->hp <= 0) /* hp¥ÎºÉ */ - i = 1; - else if (thechicken->tiredstrong > thechicken->hp * 3) /* ¾Þ³Ò¹L«× */ - i = 2; - else if (thechicken->weight > thechicken->hp_max * 5) /* ªÎD¹L«× */ - i = 3; - else if (thechicken->weight == 1 && - thechicken->sick > thechicken->hp_max / 4) - i = 4; /* ¾j¦º¤F */ - else if (thechicken->satis <= 0) /* «Ü¤£º¡·N */ - i = 5; - else - return 0; - - if (thechicken == mychicken) { - log_filef(CHICKENLOG, LOG_CREAT, - ANSI_COLOR(31) "%s" ANSI_RESET " ©Ò¯k·Rªº" ANSI_COLOR(33) " %s" ANSI_COLOR(32) " %s " - ANSI_RESET "±¾¤F ©ó %s\n", cuser.userid, thechicken->name, - chicken_type[(int)thechicken->type], ctime4(&now)); - mychicken->name[0] = 0; - } - return i; -} - -int -showdeadth(int type) -{ - switch (type) { - case 1: - more(CHICKEN_PIC "/nohp", YEA); - break; - case 2: - more(CHICKEN_PIC "/tootired", YEA); - break; - case 3: - more(CHICKEN_PIC "/toofat", YEA); - break; - case 4: - more(CHICKEN_PIC "/nofood", YEA); - break; - case 5: - more(CHICKEN_PIC "/nosatis", YEA); - break; - default: - return 0; - } - more(CHICKEN_PIC "/deadth", YEA); - return type; -} - -static int -isdeadth(const chicken_t * thechicken, chicken_t *mychicken) -{ - int i; - - if (!(i = deadtype(thechicken, mychicken))) - return 0; - return showdeadth(i); -} - -static void -ch_changename(chicken_t *mychicken) -{ - char newname[20] = ""; - - getdata_str(b_lines - 1, 0, "¶â..§ïÓ¦n¦W¦r§a:", newname, 18, DOECHO, - mychicken->name); - - if (strlen(newname) >= 3 && strcmp(newname, mychicken->name)) { - strlcpy(mychicken->name, newname, sizeof(mychicken->name)); - log_filef(CHICKENLOG, LOG_CREAT, - ANSI_COLOR(31) "%s" ANSI_RESET " §â¯k·Rªº" ANSI_COLOR(33) " %s" ANSI_COLOR(32) " %s " - ANSI_RESET "§ï¦W¬°" ANSI_COLOR(33) " %s" ANSI_RESET " ©ó %s\n", - cuser.userid, mychicken->name, - chicken_type[(int)mychicken->type], newname, ctime4(&now)); - } -} - -static int -select_menu(int age, chicken_t *mychicken) -{ - char ch; - - reload_money(); - move(19, 0); - prints(ANSI_COLOR(44;37) " ¿ú :" ANSI_COLOR(33) " %-10d " - " " ANSI_RESET "\n" - ANSI_COLOR(33) "(" ANSI_COLOR(37) "1" ANSI_COLOR(33) ")²M²z (" ANSI_COLOR(37) "2" ANSI_COLOR(33) ")¦Y¶º " - "(" ANSI_COLOR(37) "3" ANSI_COLOR(33) ")²q®± (" ANSI_COLOR(37) "4" ANSI_COLOR(33) ")°á®Ñ " - "(" ANSI_COLOR(37) "5" ANSI_COLOR(33) ")¿Ë¥L (" ANSI_COLOR(37) "6" ANSI_COLOR(33) ")¥´¥L " - "(" ANSI_COLOR(37) "7" ANSI_COLOR(33) ")¶R%s$%d (" ANSI_COLOR(37) "8" ANSI_COLOR(33) ")¦Y¸É¤Y\n" - "(" ANSI_COLOR(37) "9" ANSI_COLOR(33) ")¦Y¯fÃÄ (" ANSI_COLOR(37) "o" ANSI_COLOR(33) ")¶R¤j¸É¤Y$100 " - "(" ANSI_COLOR(37) "m" ANSI_COLOR(33) ")¶RÃÄ$10 (" ANSI_COLOR(37) "k" ANSI_COLOR(33) ")±ó¾i " - "(" ANSI_COLOR(37) "n" ANSI_COLOR(33) ")§ï¦W " - "(" ANSI_COLOR(37) "q" ANSI_COLOR(33) ")Â÷¶}:" ANSI_RESET, - cuser.money, - /* - * chicken_food[(int)mychicken->type], - * chicken_type[(int)mychicken->type], - * chicken_type[(int)mychicken->type], - */ - chicken_food[(int)mychicken->type], - food_price[(int)mychicken->type]); - do { - switch (ch = igetch()) { - case '1': - ch_clean(mychicken); - check_sick(mychicken); - break; - case '2': - ch_eat(mychicken); - check_sick(mychicken); - break; - case '3': - ch_guess(mychicken); - check_sick(mychicken); - break; - case '4': - ch_book(mychicken); - check_sick(mychicken); - break; - case '5': - ch_kiss(mychicken); - break; - case '6': - 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(mychicken); - break; - case '9': - ch_eatmedicine(mychicken); - break; - case 'O': - case 'o': - ch_buyitem(100, CHICKEN_PIC "/buyoo", &mychicken->oo, 1); - break; - case 'M': - case 'm': - ch_buyitem(10, CHICKEN_PIC "/buymedicine", &mychicken->medicine, 1); - break; - case 'N': - case 'n': - ch_changename(mychicken); - break; - case 'K': - case 'k': - ch_kill(mychicken); - return 0; - case 'Q': - case 'q': - return 0; - } - } while (ch < ' ' || ch > 'z'); - return 1; -} - -static int -recover_chicken(chicken_t * thechicken) -{ - char buf[200]; - int price = egg_price[(int)thechicken->type]; - int money = price + (random() % price); - price *= 2; - // money is a little less than price. - - if (now - thechicken->lastvisit > (60 * 60 * 24 * 7)) - return 0; - outmsg(ANSI_COLOR(33;44) "¡¹ÆF¬É¦u½Ã" ANSI_COLOR(37;45) " §O®`©È §Ú¬O¨ÓÀ°§Aªº " ANSI_RESET); - bell(); - igetch(); - outmsg(ANSI_COLOR(33;44) "¡¹ÆF¬É¦u½Ã" ANSI_COLOR(37;45) " §AµLªk¥á¨ì§Ú¤ô²y ¦]¬°§Ú¬O¸tÆF, " - "³Ìªñ¯Ê¿ú·QÁÈ¥~§Ö " ANSI_RESET); - bell(); - igetch(); - snprintf(buf, sizeof(buf), ANSI_COLOR(33;44) "¡¹ÆF¬É¦u½Ã" ANSI_COLOR(37;45) " " - "§A¦³¤@Ó訫¤£¤[ªº%sn©Û´«¦^¨Ó¶Ü? ¥un %d ¤¸ò " ANSI_RESET, - chicken_type[(int)thechicken->type], price); - outmsg(buf); - bell(); - getdata_str(21, 0, " ¿ï¾Ü¡G(N:§|¤H¹À/y:½ÐÀ°À°§Ú)", buf, 3, LCECHO, "N"); - if (buf[0] == 'y' || buf[0] == 'Y') { - reload_money(); - if (cuser.money < price) { - outmsg(ANSI_COLOR(33;44) "¡¹ÆF¬É¦u½Ã" ANSI_COLOR(37;45) " ¤°»ò ¿ú¨S±a°÷ " - "¨S¿úªº¤p° §Ö¥hÄw¿ú§a " ANSI_RESET); - bell(); - igetch(); - return 0; - } - strlcpy(thechicken->name, "[¾ß¦^¨Óªº]", sizeof(thechicken->name)); - thechicken->hp = thechicken->hp_max; - thechicken->sick = 0; - thechicken->satis = 2; - thechicken->tiredstrong = 0; - thechicken->weight = thechicken->hp; - // thechicken->lastvisit = now; // really need so? - vice(money, "ÆF¬É¦u½Ã"); - snprintf(buf, sizeof(buf), - ANSI_COLOR(33;44) "¡¹ÆF¬É¦u½Ã" ANSI_COLOR(37;45) - " OK¤F °O±oÁý¥LÂIªF¦è ¤£µM¥i¯à¥¢®Ä¡C" - "¤µ¤Ñ¤ß±¡¦n¡A®³§A$%d´N¦n " ANSI_RESET, money); - outmsg(buf); - bell(); - igetch(); - return 1; - } - outmsg(ANSI_COLOR(33;44) "¡¹ÆF¬É¦u½Ã" ANSI_COLOR(37;45) - " ³ºµM»¡§Ú§|¤H! ³o¦~ÀY©R¯u¤£È¿ú " - "°£«D§Ú¦A¨Ó§ä§A §A¦A¤]¨S¾÷·|¤F " ANSI_RESET); - bell(); - igetch(); - thechicken->lastvisit = 0; - return 0; -} - -void -chicken_toggle_death(const char *uid) -{ - chicken_t *mychicken = load_live_chicken(uid); - -#ifdef CHICKEN_LIVE_UPGRADE - // live update - vmsg("PTT ¨t²Î¶i¦æ§ó·s¡A¥»¶g¼È°±¶}©ñÃdª«³]©w¡C"); - return; -#endif - - if (!uid) - return; - if (!mychicken) - { - vmsgf("%s ¨S¾iÃdª«¡C", uid); - } - else if (mychicken->name[0]) - { - mychicken->name[0] = 0; - vmsgf("%s ªºÃdª«³Q±þ¦º¤F", uid); - } - else - { - strlcpy(mychicken->name, "[¦º]", sizeof(mychicken->name)); - vmsgf("%s ªºÃdª«´_¬¡¤F", uid); - } - free_live_chicken(mychicken); -} - -#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 - -#ifdef CHICKEN_LIVE_UPGRADE -static void -chicken_live_upgrade() -{ - char fn[PATHLEN]; - FILE *fp = NULL; - setuserfile(fn, FN_CHICKEN); - - if (dashf(fn)) - return; - - if (!cuser.old_chicken.name[0] && - !cuser.old_chicken.cbirth && - !cuser.old_chicken.hp_max) - return; - - // write to data. - fp = fopen(fn, "wb"); - fwrite(&cuser.old_chicken, sizeof(chicken_t), 1, fp); - fclose(fp); -#if 0 // enable if you want logs - log_filef("log/chicken_live_upgrade", LOG_CREAT, - "%s upgrade chicken at %s", - cuser.userid, ctime4(&now)); -#endif -} -#endif // CHICKEN_LIVE_UPGRADE - -int -chicken_main(void) -{ - int age; - chicken_t *mychicken = load_live_chicken(cuser.userid); - -#ifdef CHICKEN_LIVE_UPGRADE - if (mychicken == NULL) - { - chicken_live_upgrade(); - mychicken = load_live_chicken(cuser.userid); - } -#endif - - lockreturn0(CHICKEN, LOCK_MULTI); - 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, mychicken)) - break; - show_chicken_data(mychicken, NULL); - } while (select_menu(age, mychicken)); - unlockutmpmode(); - free_live_chicken(mychicken); - return 0; -} - -#ifdef USE_CHICKEN_PK -int -chickenpk(int fd) -{ - 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]; - int r, attmax, i, datac, catched = 0, - count = 0; - - lockreturn0(CHICKEN, LOCK_MULTI); - /* §â¹ï¤âªºid¥Îlocal buffer°O¦í */ - strlcpy(mateid, currutmp->mateid, sizeof(mateid)); - - if (!mychicken || !ochicken || - !ochicken->name[0] || !mychicken->name[0]) { - free_live_chicken(mychicken); - free_live_chicken(ochicken); - bell(); - vmsg("¦³¤@¤è¨S¦³Ãdª«"); /* Ptt:§«¤îpage®É§âÃdª«½æ±¼ */ - add_io(0, 0); - close(fd); - unlockutmpmode(); - return 0; - } - - show_chicken_data(ochicken, mychicken); - add_io(fd, 3); /* §âfd¥[¨ìigetchºÊµø */ - - while (1) { - r = random(); - ch = igetch(); - show_chicken_data(ochicken, mychicken); - time_diff(mychicken); - - i = mychicken->attack * mychicken->hp / mychicken->hp_max; - for (attmax = 2; (i = i * 9 / 10); attmax++); - - if (ch == I_OTHERDATA) { - count = 0; - datac = recv(fd, data, sizeof(data), 0); - if (datac <= 1) - break; - move(17, 0); - outs(data + 1); - switch (data[0]) { - case 'c': - catched = 1; - move(16, 0); - outs("n©ñ¥L¨«¶Ü?(y/N)"); - break; - case 'd': - move(16, 0); - outs("ªü~ˤU¤F!!"); - break; - } - if (data[0] == 'd' || data[0] == 'q' || data[0] == 'l') - break; - continue; - } else if (currutmp->turn) { - count = 0; - currutmp->turn = 0; - uin->turn = 1; - mychicken->tiredstrong++; - switch (ch) { - case 'y': - if (catched == 1) { - snprintf(data, sizeof(data), - "lÅý %s ¸¨¶]¤F\n", ochicken->name); - } - break; - case 'n': - catched = 0; - default: - case 'k': - r = r % (attmax + 2); - if (r) { - snprintf(data, sizeof(data), - "M%s %s%s %s ¶Ë¤F %d ÂI\n", mychicken->name, - damage_degree[r / 3 > 15 ? 15 : r / 3], - attack_type[(int)mychicken->type], - ochicken->name, r); - ochicken->hp -= r; - } else - snprintf(data, sizeof(data), - "M%s ı±o¤â³n¥XÀ»µL®Ä\n", mychicken->name); - break; - case 'o': - if (mychicken->oo > 0) { - mychicken->oo--; - mychicken->hp += 300; - if (mychicken->hp > mychicken->hp_max) - mychicken->hp = mychicken->hp_max; - mychicken->tiredstrong = 0; - snprintf(data, sizeof(data), "M%s ¦Y¤FÁû¤j¸É¤Y¸É¥RÅé¤O\n", - mychicken->name); - } else - snprintf(data, sizeof(data), - "M%s ·Q¦Y¤j¸É¤Y, ¥i¬O¨S¦³¤j¸É¤Y¥i¦Y\n", - mychicken->name); - break; - case 'q': - if (r % (mychicken->run + 1) > r % (ochicken->run + 1)) - snprintf(data, sizeof(data), "q%s ¸¨¶]¤F\n", - mychicken->name); - else - snprintf(data, sizeof(data), - "c%s ·Q¸¨¶], ¦ý³Q %s §ì¨ì¤F\n", - mychicken->name, ochicken->name); - break; - } - if (deadtype(ochicken, mychicken)) { - char *p = strchr(data, '\n'); - if(p) *p = '\0'; - strlcpy(buf, data, sizeof(buf)); - snprintf(data, sizeof(data), "d%s , %s ³Q %s ¥´¦º¤F\n", - buf + 1, ochicken->name, mychicken->name); - } - move(17, 0); - outs(data + 1); - i = strlen(data) + 1; - send(fd, data, i, 0); - if (data[0] == 'q' || data[0] == 'd') - break; - } else { - move(17, 0); - if (count++ > 30) - break; - } - } - add_io(0, 0); /* §âigetch«ì´_¦^ */ - pressanykey(); - close(fd); - showdeadth(deadtype(mychicken, mychicken)); - unlockutmpmode(); - free_live_chicken(mychicken); - free_live_chicken(ochicken); - return 0; -} -#endif // USE_CHICKEN_PK diff --git a/mbbsd/convert.c b/mbbsd/convert.c deleted file mode 100644 index e5d0f07b..00000000 --- a/mbbsd/convert.c +++ /dev/null @@ -1,123 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#ifdef CONVERT - -extern unsigned char *gb2big(unsigned char *, int *, int); -extern unsigned char *big2gb(unsigned char *, int *, int); -extern unsigned char *utf8_uni(unsigned char *, int *, int); -extern unsigned char *uni_utf8(unsigned char *, int *, int); -extern unsigned char *uni2big(unsigned char *, int *, int); -extern unsigned char *big2uni(unsigned char *, int *, int); - -static ssize_t -gb_input(void *buf, ssize_t icount) -{ - /* is sizeof(ssize_t) == sizeof(int)? not sure */ - int ic = (int) icount; - gb2big((unsigned char *)buf, &ic, 0); - return (ssize_t)ic; -} - -static ssize_t -gb_read(int fd, void *buf, size_t count) -{ - ssize_t icount = read(fd, buf, count); - if (icount > 0) - icount = gb_input(buf, icount); - return icount; -} - -static ssize_t -gb_write(int fd, void *buf, size_t count) -{ - int icount = (int)count; - big2gb((unsigned char *)buf, &icount, 0); - if(icount > 0) - return write(fd, buf, (size_t)icount); - else - return count; /* fake */ -} - -static ssize_t -utf8_input (void *buf, ssize_t icount) -{ - /* is sizeof(ssize_t) == sizeof(int)? not sure */ - int ic = (int) icount; - utf8_uni(buf, &ic, 0); - uni2big(buf, &ic, 0); - return (ssize_t)ic; -} - -static ssize_t -utf8_read(int fd, void *buf, size_t count) -{ - ssize_t icount = read(fd, buf, count); - if (icount > 0) - icount = utf8_input(buf, icount); - return icount; -} - -static ssize_t -utf8_write(int fd, void *buf, size_t count) -{ - int icount = (int)count; - static unsigned char *mybuf = NULL; - static int cmybuf = 0; - - /* utf8 output is a special case because - * we need larger buffer which can be - * tripple or more in size. - * Current implementation uses 128 for each block. - */ - - if(cmybuf < count * 4) { - cmybuf = (count*4+0x80) & (~0x7f) ; - mybuf = (unsigned char*) realloc (mybuf, cmybuf); - } - memcpy(mybuf, buf, count); - big2uni(mybuf, &icount, 0); - uni_utf8(mybuf, &icount, 0); - if(icount > 0) - return write(fd, mybuf, (size_t)icount); - else - return count; /* fake */ -} - -static ssize_t -norm_input(void *buf, ssize_t icount) -{ - return icount; -} - -/* global function pointers */ -read_write_type write_type = (read_write_type)write; -read_write_type read_type = read; -convert_type input_type = norm_input; - -// enable this in case some day we want to detect -// current type. but right now disable for less memory cost -// int bbs_convert_type = CONV_NORMAL; - -void set_converting_type(int which) -{ - if (which == CONV_NORMAL) { - read_type = read; - write_type = (read_write_type)write; - /* for speed up, NULL is better.. */ - input_type = NULL; /* norm_input; */ - } - else if (which == CONV_GB) { - read_type = gb_read; - write_type = gb_write; - input_type = gb_input; - } - else if (which == CONV_UTF8) { - read_type = utf8_read; - write_type = utf8_write; - input_type = utf8_input; - } - // bbs_convert_type = which; -} - -#endif diff --git a/mbbsd/crypt.c b/mbbsd/crypt.c deleted file mode 100644 index 7283c8a6..00000000 --- a/mbbsd/crypt.c +++ /dev/null @@ -1,647 +0,0 @@ -/* $Id */ -/* This file is crypt.c taken from ssh 1.2.33, only modified for compile */ -/** - * FreeBSD ¤Î Linux glibc ªþªº crypt() ³£·|¥Î¨ì¤j table ¥[³t¦h¦¸ crypt(). - * ¦ý bbs ¶È¤W¯¸Àˬd±K½X®É¨Ï¥Î¤@¦¸, ¤£È±o¬°¦¹ªá 100kb memory. (non-const memory) - * libdes ªº crypt() ¶È»Ý 4kb ªº constant lookup table. - * - * ¤£¹Lnª`·N libdes 4.01 ªº license ¸ò GPL ¤£¦X, ¦]¦¹¦¹³B±Ä¥Î ssh 1.2.33 ¸ÌÀY - * ªþªº crypt.c derived from libdes 3.06, ¸Óª©ªº libdes ¬O GPL ªº. - */ -#define PROTO -/* This file is fcrypt.c taken from SSLeay-0.4.3a. This file is only compiled - in on those systems that don't have crypt() in the system libraries. - //ylo */ - -/* fcrypt.c */ -/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). - * All rights reserved. - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * See the COPYRIGHT file in the libdes distribution for more details. - */ - -#include <stdio.h> -#define _LIBC - -/* Eric Young. - * This version of crypt has been developed from my MIT compatable - * DES library. - * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au - * eay@mincom.oz.au or eay@psych.psy.uq.oz.au - */ - -#if !defined(_LIBC) || defined(NOCONST) -#define const -#endif - -typedef unsigned char des_cblock[8]; - -typedef struct des_ks_struct - { - union { - des_cblock _; - /* make sure things are correct size on machines with - * 8 byte longs */ - unsigned long pad[2]; - } ks; -#define _ ks._ - } des_key_schedule[16]; - -#define DES_KEY_SZ (sizeof(des_cblock)) -#define DES_ENCRYPT 1 -#define DES_DECRYPT 0 - -#define ITERATIONS 16 -#define HALF_ITERATIONS 8 - -#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ - l|=((unsigned long)(*((c)++)))<< 8, \ - l|=((unsigned long)(*((c)++)))<<16, \ - l|=((unsigned long)(*((c)++)))<<24) - -#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24)&0xff)) - -static const unsigned long SPtrans[8][64]={ -/* nibble 0 */ -{ -0x00820200, 0x00020000, 0x80800000, 0x80820200, -0x00800000, 0x80020200, 0x80020000, 0x80800000, -0x80020200, 0x00820200, 0x00820000, 0x80000200, -0x80800200, 0x00800000, 0x00000000, 0x80020000, -0x00020000, 0x80000000, 0x00800200, 0x00020200, -0x80820200, 0x00820000, 0x80000200, 0x00800200, -0x80000000, 0x00000200, 0x00020200, 0x80820000, -0x00000200, 0x80800200, 0x80820000, 0x00000000, -0x00000000, 0x80820200, 0x00800200, 0x80020000, -0x00820200, 0x00020000, 0x80000200, 0x00800200, -0x80820000, 0x00000200, 0x00020200, 0x80800000, -0x80020200, 0x80000000, 0x80800000, 0x00820000, -0x80820200, 0x00020200, 0x00820000, 0x80800200, -0x00800000, 0x80000200, 0x80020000, 0x00000000, -0x00020000, 0x00800000, 0x80800200, 0x00820200, -0x80000000, 0x80820000, 0x00000200, 0x80020200, -}, -/* nibble 1 */ -{ -0x10042004, 0x00000000, 0x00042000, 0x10040000, -0x10000004, 0x00002004, 0x10002000, 0x00042000, -0x00002000, 0x10040004, 0x00000004, 0x10002000, -0x00040004, 0x10042000, 0x10040000, 0x00000004, -0x00040000, 0x10002004, 0x10040004, 0x00002000, -0x00042004, 0x10000000, 0x00000000, 0x00040004, -0x10002004, 0x00042004, 0x10042000, 0x10000004, -0x10000000, 0x00040000, 0x00002004, 0x10042004, -0x00040004, 0x10042000, 0x10002000, 0x00042004, -0x10042004, 0x00040004, 0x10000004, 0x00000000, -0x10000000, 0x00002004, 0x00040000, 0x10040004, -0x00002000, 0x10000000, 0x00042004, 0x10002004, -0x10042000, 0x00002000, 0x00000000, 0x10000004, -0x00000004, 0x10042004, 0x00042000, 0x10040000, -0x10040004, 0x00040000, 0x00002004, 0x10002000, -0x10002004, 0x00000004, 0x10040000, 0x00042000, -}, -/* nibble 2 */ -{ -0x41000000, 0x01010040, 0x00000040, 0x41000040, -0x40010000, 0x01000000, 0x41000040, 0x00010040, -0x01000040, 0x00010000, 0x01010000, 0x40000000, -0x41010040, 0x40000040, 0x40000000, 0x41010000, -0x00000000, 0x40010000, 0x01010040, 0x00000040, -0x40000040, 0x41010040, 0x00010000, 0x41000000, -0x41010000, 0x01000040, 0x40010040, 0x01010000, -0x00010040, 0x00000000, 0x01000000, 0x40010040, -0x01010040, 0x00000040, 0x40000000, 0x00010000, -0x40000040, 0x40010000, 0x01010000, 0x41000040, -0x00000000, 0x01010040, 0x00010040, 0x41010000, -0x40010000, 0x01000000, 0x41010040, 0x40000000, -0x40010040, 0x41000000, 0x01000000, 0x41010040, -0x00010000, 0x01000040, 0x41000040, 0x00010040, -0x01000040, 0x00000000, 0x41010000, 0x40000040, -0x41000000, 0x40010040, 0x00000040, 0x01010000, -}, -/* nibble 3 */ -{ -0x00100402, 0x04000400, 0x00000002, 0x04100402, -0x00000000, 0x04100000, 0x04000402, 0x00100002, -0x04100400, 0x04000002, 0x04000000, 0x00000402, -0x04000002, 0x00100402, 0x00100000, 0x04000000, -0x04100002, 0x00100400, 0x00000400, 0x00000002, -0x00100400, 0x04000402, 0x04100000, 0x00000400, -0x00000402, 0x00000000, 0x00100002, 0x04100400, -0x04000400, 0x04100002, 0x04100402, 0x00100000, -0x04100002, 0x00000402, 0x00100000, 0x04000002, -0x00100400, 0x04000400, 0x00000002, 0x04100000, -0x04000402, 0x00000000, 0x00000400, 0x00100002, -0x00000000, 0x04100002, 0x04100400, 0x00000400, -0x04000000, 0x04100402, 0x00100402, 0x00100000, -0x04100402, 0x00000002, 0x04000400, 0x00100402, -0x00100002, 0x00100400, 0x04100000, 0x04000402, -0x00000402, 0x04000000, 0x04000002, 0x04100400, -}, -/* nibble 4 */ -{ -0x02000000, 0x00004000, 0x00000100, 0x02004108, -0x02004008, 0x02000100, 0x00004108, 0x02004000, -0x00004000, 0x00000008, 0x02000008, 0x00004100, -0x02000108, 0x02004008, 0x02004100, 0x00000000, -0x00004100, 0x02000000, 0x00004008, 0x00000108, -0x02000100, 0x00004108, 0x00000000, 0x02000008, -0x00000008, 0x02000108, 0x02004108, 0x00004008, -0x02004000, 0x00000100, 0x00000108, 0x02004100, -0x02004100, 0x02000108, 0x00004008, 0x02004000, -0x00004000, 0x00000008, 0x02000008, 0x02000100, -0x02000000, 0x00004100, 0x02004108, 0x00000000, -0x00004108, 0x02000000, 0x00000100, 0x00004008, -0x02000108, 0x00000100, 0x00000000, 0x02004108, -0x02004008, 0x02004100, 0x00000108, 0x00004000, -0x00004100, 0x02004008, 0x02000100, 0x00000108, -0x00000008, 0x00004108, 0x02004000, 0x02000008, -}, -/* nibble 5 */ -{ -0x20000010, 0x00080010, 0x00000000, 0x20080800, -0x00080010, 0x00000800, 0x20000810, 0x00080000, -0x00000810, 0x20080810, 0x00080800, 0x20000000, -0x20000800, 0x20000010, 0x20080000, 0x00080810, -0x00080000, 0x20000810, 0x20080010, 0x00000000, -0x00000800, 0x00000010, 0x20080800, 0x20080010, -0x20080810, 0x20080000, 0x20000000, 0x00000810, -0x00000010, 0x00080800, 0x00080810, 0x20000800, -0x00000810, 0x20000000, 0x20000800, 0x00080810, -0x20080800, 0x00080010, 0x00000000, 0x20000800, -0x20000000, 0x00000800, 0x20080010, 0x00080000, -0x00080010, 0x20080810, 0x00080800, 0x00000010, -0x20080810, 0x00080800, 0x00080000, 0x20000810, -0x20000010, 0x20080000, 0x00080810, 0x00000000, -0x00000800, 0x20000010, 0x20000810, 0x20080800, -0x20080000, 0x00000810, 0x00000010, 0x20080010, -}, -/* nibble 6 */ -{ -0x00001000, 0x00000080, 0x00400080, 0x00400001, -0x00401081, 0x00001001, 0x00001080, 0x00000000, -0x00400000, 0x00400081, 0x00000081, 0x00401000, -0x00000001, 0x00401080, 0x00401000, 0x00000081, -0x00400081, 0x00001000, 0x00001001, 0x00401081, -0x00000000, 0x00400080, 0x00400001, 0x00001080, -0x00401001, 0x00001081, 0x00401080, 0x00000001, -0x00001081, 0x00401001, 0x00000080, 0x00400000, -0x00001081, 0x00401000, 0x00401001, 0x00000081, -0x00001000, 0x00000080, 0x00400000, 0x00401001, -0x00400081, 0x00001081, 0x00001080, 0x00000000, -0x00000080, 0x00400001, 0x00000001, 0x00400080, -0x00000000, 0x00400081, 0x00400080, 0x00001080, -0x00000081, 0x00001000, 0x00401081, 0x00400000, -0x00401080, 0x00000001, 0x00001001, 0x00401081, -0x00400001, 0x00401080, 0x00401000, 0x00001001, -}, -/* nibble 7 */ -{ -0x08200020, 0x08208000, 0x00008020, 0x00000000, -0x08008000, 0x00200020, 0x08200000, 0x08208020, -0x00000020, 0x08000000, 0x00208000, 0x00008020, -0x00208020, 0x08008020, 0x08000020, 0x08200000, -0x00008000, 0x00208020, 0x00200020, 0x08008000, -0x08208020, 0x08000020, 0x00000000, 0x00208000, -0x08000000, 0x00200000, 0x08008020, 0x08200020, -0x00200000, 0x00008000, 0x08208000, 0x00000020, -0x00200000, 0x00008000, 0x08000020, 0x08208020, -0x00008020, 0x08000000, 0x00000000, 0x00208000, -0x08200020, 0x08008020, 0x08008000, 0x00200020, -0x08208000, 0x00000020, 0x00200020, 0x08008000, -0x08208020, 0x00200000, 0x08200000, 0x08000020, -0x00208000, 0x00008020, 0x08008020, 0x08200000, -0x00000020, 0x08208000, 0x00208020, 0x00000000, -0x08000000, 0x08200020, 0x00008000, 0x00208020}}; -static const unsigned long skb[8][64]={ -/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ -{ -0x00000000,0x00000010,0x20000000,0x20000010, -0x00010000,0x00010010,0x20010000,0x20010010, -0x00000800,0x00000810,0x20000800,0x20000810, -0x00010800,0x00010810,0x20010800,0x20010810, -0x00000020,0x00000030,0x20000020,0x20000030, -0x00010020,0x00010030,0x20010020,0x20010030, -0x00000820,0x00000830,0x20000820,0x20000830, -0x00010820,0x00010830,0x20010820,0x20010830, -0x00080000,0x00080010,0x20080000,0x20080010, -0x00090000,0x00090010,0x20090000,0x20090010, -0x00080800,0x00080810,0x20080800,0x20080810, -0x00090800,0x00090810,0x20090800,0x20090810, -0x00080020,0x00080030,0x20080020,0x20080030, -0x00090020,0x00090030,0x20090020,0x20090030, -0x00080820,0x00080830,0x20080820,0x20080830, -0x00090820,0x00090830,0x20090820,0x20090830, -}, -/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ -{ -0x00000000,0x02000000,0x00002000,0x02002000, -0x00200000,0x02200000,0x00202000,0x02202000, -0x00000004,0x02000004,0x00002004,0x02002004, -0x00200004,0x02200004,0x00202004,0x02202004, -0x00000400,0x02000400,0x00002400,0x02002400, -0x00200400,0x02200400,0x00202400,0x02202400, -0x00000404,0x02000404,0x00002404,0x02002404, -0x00200404,0x02200404,0x00202404,0x02202404, -0x10000000,0x12000000,0x10002000,0x12002000, -0x10200000,0x12200000,0x10202000,0x12202000, -0x10000004,0x12000004,0x10002004,0x12002004, -0x10200004,0x12200004,0x10202004,0x12202004, -0x10000400,0x12000400,0x10002400,0x12002400, -0x10200400,0x12200400,0x10202400,0x12202400, -0x10000404,0x12000404,0x10002404,0x12002404, -0x10200404,0x12200404,0x10202404,0x12202404, -}, -/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ -{ -0x00000000,0x00000001,0x00040000,0x00040001, -0x01000000,0x01000001,0x01040000,0x01040001, -0x00000002,0x00000003,0x00040002,0x00040003, -0x01000002,0x01000003,0x01040002,0x01040003, -0x00000200,0x00000201,0x00040200,0x00040201, -0x01000200,0x01000201,0x01040200,0x01040201, -0x00000202,0x00000203,0x00040202,0x00040203, -0x01000202,0x01000203,0x01040202,0x01040203, -0x08000000,0x08000001,0x08040000,0x08040001, -0x09000000,0x09000001,0x09040000,0x09040001, -0x08000002,0x08000003,0x08040002,0x08040003, -0x09000002,0x09000003,0x09040002,0x09040003, -0x08000200,0x08000201,0x08040200,0x08040201, -0x09000200,0x09000201,0x09040200,0x09040201, -0x08000202,0x08000203,0x08040202,0x08040203, -0x09000202,0x09000203,0x09040202,0x09040203, -}, -/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ -{ -0x00000000,0x00100000,0x00000100,0x00100100, -0x00000008,0x00100008,0x00000108,0x00100108, -0x00001000,0x00101000,0x00001100,0x00101100, -0x00001008,0x00101008,0x00001108,0x00101108, -0x04000000,0x04100000,0x04000100,0x04100100, -0x04000008,0x04100008,0x04000108,0x04100108, -0x04001000,0x04101000,0x04001100,0x04101100, -0x04001008,0x04101008,0x04001108,0x04101108, -0x00020000,0x00120000,0x00020100,0x00120100, -0x00020008,0x00120008,0x00020108,0x00120108, -0x00021000,0x00121000,0x00021100,0x00121100, -0x00021008,0x00121008,0x00021108,0x00121108, -0x04020000,0x04120000,0x04020100,0x04120100, -0x04020008,0x04120008,0x04020108,0x04120108, -0x04021000,0x04121000,0x04021100,0x04121100, -0x04021008,0x04121008,0x04021108,0x04121108, -}, -/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ -{ -0x00000000,0x10000000,0x00010000,0x10010000, -0x00000004,0x10000004,0x00010004,0x10010004, -0x20000000,0x30000000,0x20010000,0x30010000, -0x20000004,0x30000004,0x20010004,0x30010004, -0x00100000,0x10100000,0x00110000,0x10110000, -0x00100004,0x10100004,0x00110004,0x10110004, -0x20100000,0x30100000,0x20110000,0x30110000, -0x20100004,0x30100004,0x20110004,0x30110004, -0x00001000,0x10001000,0x00011000,0x10011000, -0x00001004,0x10001004,0x00011004,0x10011004, -0x20001000,0x30001000,0x20011000,0x30011000, -0x20001004,0x30001004,0x20011004,0x30011004, -0x00101000,0x10101000,0x00111000,0x10111000, -0x00101004,0x10101004,0x00111004,0x10111004, -0x20101000,0x30101000,0x20111000,0x30111000, -0x20101004,0x30101004,0x20111004,0x30111004, -}, -/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ -{ -0x00000000,0x08000000,0x00000008,0x08000008, -0x00000400,0x08000400,0x00000408,0x08000408, -0x00020000,0x08020000,0x00020008,0x08020008, -0x00020400,0x08020400,0x00020408,0x08020408, -0x00000001,0x08000001,0x00000009,0x08000009, -0x00000401,0x08000401,0x00000409,0x08000409, -0x00020001,0x08020001,0x00020009,0x08020009, -0x00020401,0x08020401,0x00020409,0x08020409, -0x02000000,0x0A000000,0x02000008,0x0A000008, -0x02000400,0x0A000400,0x02000408,0x0A000408, -0x02020000,0x0A020000,0x02020008,0x0A020008, -0x02020400,0x0A020400,0x02020408,0x0A020408, -0x02000001,0x0A000001,0x02000009,0x0A000009, -0x02000401,0x0A000401,0x02000409,0x0A000409, -0x02020001,0x0A020001,0x02020009,0x0A020009, -0x02020401,0x0A020401,0x02020409,0x0A020409, -}, -/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ -{ -0x00000000,0x00000100,0x00080000,0x00080100, -0x01000000,0x01000100,0x01080000,0x01080100, -0x00000010,0x00000110,0x00080010,0x00080110, -0x01000010,0x01000110,0x01080010,0x01080110, -0x00200000,0x00200100,0x00280000,0x00280100, -0x01200000,0x01200100,0x01280000,0x01280100, -0x00200010,0x00200110,0x00280010,0x00280110, -0x01200010,0x01200110,0x01280010,0x01280110, -0x00000200,0x00000300,0x00080200,0x00080300, -0x01000200,0x01000300,0x01080200,0x01080300, -0x00000210,0x00000310,0x00080210,0x00080310, -0x01000210,0x01000310,0x01080210,0x01080310, -0x00200200,0x00200300,0x00280200,0x00280300, -0x01200200,0x01200300,0x01280200,0x01280300, -0x00200210,0x00200310,0x00280210,0x00280310, -0x01200210,0x01200310,0x01280210,0x01280310, -}, -/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ -{ -0x00000000,0x04000000,0x00040000,0x04040000, -0x00000002,0x04000002,0x00040002,0x04040002, -0x00002000,0x04002000,0x00042000,0x04042000, -0x00002002,0x04002002,0x00042002,0x04042002, -0x00000020,0x04000020,0x00040020,0x04040020, -0x00000022,0x04000022,0x00040022,0x04040022, -0x00002020,0x04002020,0x00042020,0x04042020, -0x00002022,0x04002022,0x00042022,0x04042022, -0x00000800,0x04000800,0x00040800,0x04040800, -0x00000802,0x04000802,0x00040802,0x04040802, -0x00002800,0x04002800,0x00042800,0x04042800, -0x00002802,0x04002802,0x00042802,0x04042802, -0x00000820,0x04000820,0x00040820,0x04040820, -0x00000822,0x04000822,0x00040822,0x04040822, -0x00002820,0x04002820,0x00042820,0x04042820, -0x00002822,0x04002822,0x00042822,0x04042822, -} -}; - -/* See ecb_encrypt.c for a pseudo description of these macros. */ -#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ - (b)^=(t),\ - (a)^=((t)<<(n))) - -#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ - (a)=(a)^(t)^(t>>(16-(n))))\ - -static const char shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; - -#ifdef PROTO -static int body(unsigned long *out0, unsigned long *out1, des_key_schedule ks, unsigned long Eswap0, unsigned long Eswap1); -static int des_set_key(des_cblock (*key), struct des_ks_struct *schedule); -#else -static int body(); -static int des_set_key(); -#endif - -static int des_set_key(key, schedule) -des_cblock (*key); -struct des_ks_struct *schedule; - { - register unsigned long c,d,t,s; - register unsigned char *in; - register unsigned long *k; - register int i; - - k=(unsigned long *)schedule; - in=(unsigned char *)key; - - c2l(in,c); - c2l(in,d); - - /* I now do it in 47 simple operations :-) - * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) - * for the inspiration. :-) */ - PERM_OP (d,c,t,4,0x0f0f0f0f); - HPERM_OP(c,t,-2,0xcccc0000); - HPERM_OP(d,t,-2,0xcccc0000); - PERM_OP (d,c,t,1,0x55555555); - PERM_OP (c,d,t,8,0x00ff00ff); - PERM_OP (d,c,t,1,0x55555555); - d= (((d&0x000000ff)<<16)| (d&0x0000ff00) | - ((d&0x00ff0000)>>16)|((c&0xf0000000)>>4)); - c&=0x0fffffff; - - for (i=0; i<ITERATIONS; i++) - { - if (shifts2[i]) - { c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); } - else - { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); } - c&=0x0fffffff; - d&=0x0fffffff; - /* could be a few less shifts but I am to lazy at this - * point in time to investigate */ - s= skb[0][ (c )&0x3f ]| - skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)]| - skb[2][((c>>13)&0x0f)|((c>>14)&0x30)]| - skb[3][((c>>20)&0x01)|((c>>21)&0x06) | - ((c>>22)&0x38)]; - t= skb[4][ (d )&0x3f ]| - skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)]| - skb[6][ (d>>15)&0x3f ]| - skb[7][((d>>21)&0x0f)|((d>>22)&0x30)]; - - /* table contained 0213 4657 */ - *(k++)=((t<<16)|(s&0x0000ffff))&0xffffffff; - s= ((s>>16)|(t&0xffff0000)); - - s=(s<<4)|(s>>28); - *(k++)=s&0xffffffff; - } - return(0); - } - -/****************************************************************** - * modified stuff for crypt. - ******************************************************************/ - -/* The changes to this macro may help or hinder, depending on the - * compiler and the achitecture. gcc2 always seems to do well :-). - * Inspired by Dana How <how@isl.stanford.edu> - * DO NOT use the alternative version on machines with 8 byte longs. - */ -#ifdef ALT_ECB -#define D_ENCRYPT(L,R,S) \ - t=(R^(R>>16)); \ - u=(t&E0); \ - t=(t&E1); \ - u=((u^(u<<16))^R^s[S ])<<2; \ - t=(t^(t<<16))^R^s[S+1]; \ - t=(t>>2)|(t<<30); \ - L^= \ - *(unsigned long *)(des_SP+0x0100+((t )&0xfc))+ \ - *(unsigned long *)(des_SP+0x0300+((t>> 8)&0xfc))+ \ - *(unsigned long *)(des_SP+0x0500+((t>>16)&0xfc))+ \ - *(unsigned long *)(des_SP+0x0700+((t>>24)&0xfc))+ \ - *(unsigned long *)(des_SP+ ((u )&0xfc))+ \ - *(unsigned long *)(des_SP+0x0200+((u>> 8)&0xfc))+ \ - *(unsigned long *)(des_SP+0x0400+((u>>16)&0xfc))+ \ - *(unsigned long *)(des_SP+0x0600+((u>>24)&0xfc)); -#else /* original version */ -#define D_ENCRYPT(L,R,S) \ - t=(R^(R>>16)); \ - u=(t&E0); \ - t=(t&E1); \ - u=(u^(u<<16))^R^s[S ]; \ - t=(t^(t<<16))^R^s[S+1]; \ - t=(t>>4)|(t<<28); \ - L^= SPtrans[1][(t )&0x3f]| \ - SPtrans[3][(t>> 8)&0x3f]| \ - SPtrans[5][(t>>16)&0x3f]| \ - SPtrans[7][(t>>24)&0x3f]| \ - SPtrans[0][(u )&0x3f]| \ - SPtrans[2][(u>> 8)&0x3f]| \ - SPtrans[4][(u>>16)&0x3f]| \ - SPtrans[6][(u>>24)&0x3f]; -#endif - -static unsigned const char con_salt[128]={ -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, -0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, -0x0A,0x0B,0x05,0x06,0x07,0x08,0x09,0x0A, -0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12, -0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A, -0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22, -0x23,0x24,0x25,0x20,0x21,0x22,0x23,0x24, -0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C, -0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34, -0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C, -0x3D,0x3E,0x3F,0x00,0x00,0x00,0x00,0x00, -}; - -static unsigned const char cov_2char[64]={ -0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35, -0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44, -0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C, -0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54, -0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62, -0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A, -0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72, -0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A -}; - -#ifdef PERL5 -char *des_crypt(buf,salt) -#else -char *crypt(buf, salt) -char *buf; -char *salt; - - -#endif - - - { - unsigned int i,j,x,y; - unsigned long Eswap0=0,Eswap1=0; - unsigned long out[2],ll; - des_cblock key; - des_key_schedule ks; - static unsigned char buff[20]; - unsigned char bb[9]; - unsigned char *b=bb; - unsigned char c,u; - - /* eay 25/08/92 - * If you call crypt("pwd","*") as often happens when you - * have * as the pwd field in /etc/passwd, the function - * returns *\0XXXXXXXXX - * The \0 makes the string look like * so the pwd "*" would - * crypt to "*". This was found when replacing the crypt in - * our shared libraries. People found that the disbled - * accounts effectivly had no passwd :-(. */ - x=buff[0]=((salt[0] == '\0')?'A':salt[0]); - Eswap0=con_salt[x]; - x=buff[1]=((salt[1] == '\0')?'A':salt[1]); - Eswap1=con_salt[x]<<4; - - for (i=0; i<8; i++) - { - c= *(buf++); - if (!c) break; - key[i]=(c<<1); - } - for (; i<8; i++) - key[i]=0; - - des_set_key((des_cblock *)(key),ks); - body(&(out[0]),&(out[1]),ks,Eswap0,Eswap1); - - ll=out[0]; l2c(ll,b); - ll=out[1]; l2c(ll,b); - y=0; - u=0x80; - bb[8]=0; - for (i=2; i<13; i++) - { - c=0; - for (j=0; j<6; j++) - { - c<<=1; - if (bb[y] & u) c|=1; - u>>=1; - if (!u) - { - y++; - u=0x80; - } - } - buff[i]=cov_2char[c]; - } - buff[13]='\0'; - return((char *)buff); - } - -static int body(out0, out1, ks, Eswap0, Eswap1) -unsigned long *out0; -unsigned long *out1; -des_key_schedule ks; -unsigned long Eswap0; -unsigned long Eswap1; - { - register unsigned long l,r,t,u; -#ifdef ALT_ECB - register unsigned char *des_SP=(unsigned char *)SPtrans; -#endif - register unsigned long *s; - register int i,j; - register unsigned long E0,E1; - - l=0; - r=0; - - s=(unsigned long *)ks; - E0=Eswap0; - E1=Eswap1; - - for (j=0; j<25; j++) - { - for (i=0; i<(ITERATIONS*2); i+=4) - { - D_ENCRYPT(l,r, i); /* 1 */ - D_ENCRYPT(r,l, i+2); /* 2 */ - } - t=l; - l=r; - r=t; - } - t=r; - r=(l>>1)|(l<<31); - l=(t>>1)|(t<<31); - /* clear the top bits on machines with 8byte longs */ - l&=0xffffffff; - r&=0xffffffff; - - PERM_OP(r,l,t, 1,0x55555555); - PERM_OP(l,r,t, 8,0x00ff00ff); - PERM_OP(r,l,t, 2,0x33333333); - PERM_OP(l,r,t,16,0x0000ffff); - PERM_OP(r,l,t, 4,0x0f0f0f0f); - - *out0=l; - *out1=r; - return(0); - } - diff --git a/mbbsd/dark.c b/mbbsd/dark.c deleted file mode 100644 index f19184dc..00000000 --- a/mbbsd/dark.c +++ /dev/null @@ -1,565 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#define RED 1 -#define BLACK 0 -typedef short int sint; - -typedef struct item { - short int color, value, die, out; -} item; - -typedef struct cur { - short int y, x, end; -} cur; - -struct DarkData { - item brd[4][8]; - cur curr; - sint rcount, bcount, cont, fix; /* cont:¬O§_¥i³s¦Y */ - sint my, mx, mly, mlx; /* ²¾°Êªº®y¼Ð ¼Ð */ - - sint cur_eaty, cur_eatx; /* ¦Y±¼¹ï¤è¨ä¤lªº¨q¥X®y¼Ð */ -}; - -static char * const rname[] = {"§L", "¬¶", "ØX", "¨®", "¬Û", "¥K", "«Ó"}; -static char * const bname[] = {"¨ò", "¥]", "°¨", "¨®", "¶H", "¤h", "±N"}; - -static const sint cury[] = {3, 5, 7, 9}, curx[] = {5, 9, 13, 17, 21, 25, 29, 33}; - -static void -brdswap(struct DarkData *dd, sint y, sint x, sint ly, sint lx) -{ - memcpy(&dd->brd[y][x], &dd->brd[ly][lx], sizeof(item)); - dd->brd[ly][lx].die = 1; - dd->brd[ly][lx].color = -1; /* ¨S³oÓcolor */ - dd->brd[ly][lx].value = -1; -} - -static sint -Is_win(struct DarkData *dd, item att, item det, sint y, sint x, sint ly, sint lx) -{ - sint i, c = 0, min, max; - if (att.value == 1) { /* ¯¥ */ - if (y != ly && x != lx) - return 0; - if ((abs(ly - y) == 1 && dd->brd[y][x].die == 0) || - (abs(lx - x) == 1 && dd->brd[y][x].die == 0)) - return 0; - if (y == ly) { - if (x > lx) { - max = x; - min = lx; - } else { - max = lx; - min = x; - } - for (i = min + 1; i < max; i++) - if (dd->brd[y][i].die == 0) - c++; - } else if (x == lx) { - if (y > ly) { - max = y; - min = ly; - } else { - max = ly; - min = y; - } - for (i = min + 1; i < max; i++) - if (dd->brd[i][x].die == 0) - c++; - } - if (c != 1) - return 0; - if (det.die == 1) - return 0; - return 1; - } - /* «D¯¥ */ - if (((abs(ly - y) == 1 && x == lx) || (abs(lx - x) == 1 && ly == y)) && dd->brd[y][x].out == 1) { - if (att.value == 0 && det.value == 6) - return 1; - else if (att.value == 6 && det.value == 0) - return 0; - else if (att.value >= det.value) - return 1; - else - return 0; - } - return 0; -} - -static sint -Is_move(struct DarkData *dd, sint y, sint x, sint ly, sint lx) -{ - if (dd->brd[y][x].die == 1 && ((abs(ly - y) == 1 && x == lx) || (abs(lx - x) == 1 && ly == y))) - return 1; - return 0; -} - -static void -brd_rand(struct DarkData *dd) -{ - sint y, x, index; - sint tem[32]; - sint value[32] = { - 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, - 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6 - }; - - bzero(dd->brd, sizeof(dd->brd)); - bzero(tem, sizeof(tem)); - bzero(&dd->curr, sizeof(dd->curr)); - for (y = 0; y < 4; y++) - for (x = 0; x < 8; x++) - while (1) { - index = random() % 32; - if (tem[index]) - continue; - dd->brd[y][x].color = (index > 15) ? 0 : 1; - dd->brd[y][x].value = value[index]; - tem[index] = 1; - break; - } -} - -static void -brd_prints(void) -{ - clear(); - move(1, 0); - outs("\n" - " " ANSI_COLOR(43;30) "¢~¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢¡" ANSI_RESET "\n" - " " ANSI_COLOR(43;30) "¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x" ANSI_RESET "\n" - " " ANSI_COLOR(43;30) "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t" ANSI_RESET "\n" - " " ANSI_COLOR(43;30) "¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x" ANSI_RESET "\n" - " " ANSI_COLOR(43;30) "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t" ANSI_RESET "\n" - " " ANSI_COLOR(43;30) "¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x" ANSI_RESET "\n" - " " ANSI_COLOR(43;30) "¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t" ANSI_RESET "\n" - " " ANSI_COLOR(43;30) "¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x¡´¢x" ANSI_RESET "\n" - " " ANSI_COLOR(43;30) "¢¢¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢£" ANSI_RESET "\n" - " "); -} - -static void -draw_line(struct DarkData *dd, sint y, sint f) -{ - sint i; - char buf[1024], tmp[256]; - - *buf = 0; - *tmp = 0; - strlcpy(buf, ANSI_COLOR(43;30), sizeof(buf)); - for (i = 0; i < 8; i++) { - if (dd->brd[y][i].die == 1) - snprintf(tmp, sizeof(tmp), "¢x "); - else if (dd->brd[y][i].out == 0) - snprintf(tmp, sizeof(tmp), "¢x¡´"); - else { - snprintf(tmp, sizeof(tmp), "¢x" ANSI_COLOR(%s1;%d) "%s" ANSI_RESET ANSI_COLOR(43;30) "", - (f == i) ? "1;47;" : "", (dd->brd[y][i].color) ? 31 : 34, - (dd->brd[y][i].color) ? rname[dd->brd[y][i].value] : - bname[dd->brd[y][i].value]); - } - strcat(buf, tmp); - } - strcat(buf, "¢x" ANSI_RESET); - - move(cury[y], 3); - clrtoeol(); - outs(buf); -} - -static void -redraw(struct DarkData *dd) -{ - sint i = 0; - for (; i < 4; i++) - draw_line(dd, i, -1); -} - -static sint -playing(struct DarkData *dd, sint fd, sint color, sint ch, sint * b, userinfo_t * uin) -{ - dd->curr.end = 0; - move(cury[dd->my], curx[dd->mx]); - - if (dd->fix) { - if (ch == 's') { - dd->fix = 0; - *b = 0; - return 0; - } else { - draw_line(dd, dd->mly, -1); - } - } - switch (ch) { - case KEY_LEFT: - if (dd->mx == 0) - dd->mx = 7; - else - dd->mx--; - move(cury[dd->my], curx[dd->mx]); - *b = -1; - break; - case KEY_RIGHT: - if (dd->mx == 7) - dd->mx = 0; - else - dd->mx++; - move(cury[dd->my], curx[dd->mx]); - *b = -1; - break; - case KEY_UP: - if (dd->my == 0) - dd->my = 3; - else - dd->my--; - move(cury[dd->my], curx[dd->mx]); - *b = -1; - break; - case KEY_DOWN: - if (dd->my == 3) - dd->my = 0; - else - dd->my++; - move(cury[dd->my], curx[dd->mx]); - *b = -1; - break; - case 'q': - case 'Q': - if (!color) - dd->bcount = 0; - else - dd->rcount = 0; - *b = 0; - return -2; - case 'p': - case 'P': - return -3; - case 'c': - return -4; - case 'g': - return -5; - case 's': /* ½¶}´Ñ¤l ©Î¬O¿ï¾Ü´Ñ¤l */ - /* ¿ï¾Ü´Ñ¤l */ - if (dd->brd[dd->my][dd->mx].out == 1) { - if (dd->brd[dd->my][dd->mx].color != color) { - *b = -1; - break; - } - if (dd->mly < 0) { /* ¥i¥H¿ï¾Ü */ - dd->mly = dd->my; - dd->mlx = dd->mx; - draw_line(dd, dd->my, dd->mx); - *b = -1; - break; - } else if (dd->mly == dd->my && dd->mlx == dd->mx) { /* ¤£¿ï¤F */ - dd->mly = -1; - dd->mlx = -1; - draw_line(dd, dd->my, -1); - } else { - draw_line(dd, dd->mly, -1); - dd->mly = dd->my; - dd->mlx = dd->mx; - if (dd->brd[dd->mly][dd->mlx].value == 1) - dd->fix = 1; - draw_line(dd, dd->my, dd->mx); - } - *b = -1; - break; - } - /* ½¶}´Ñ¤l */ - if (dd->mly >= 0) { - *b = -1; - break; - } /* ¥»¨Ó´N¬O½¶}ªº */ - /* ¨M©w¤@¶}©lªºÃC¦â */ - if (currutmp->color == '.') { - if (uin->color != '1' && uin->color != '0') - currutmp->color = (dd->brd[dd->my][dd->mx].color) ? '1' : '0'; - else - currutmp->color = (uin->color == '0') ? '1' : '0'; - } - dd->brd[dd->my][dd->mx].out = 1; - draw_line(dd, dd->my, -1); - move(cury[dd->my], curx[dd->mx]); - *b = 0; - break; - case 'u': - move(0, 0); - clrtoeol(); - prints("%s¦â%s cont=%d", - (dd->brd[dd->my][dd->mx].color == RED) ? "¬õ" : "¶Â", - rname[dd->brd[dd->my][dd->mx].value], dd->cont); - *b = -1; - break; - case '\r': /* ¦Y or ²¾°Ê ly¸òlx¥²¶·¤j©ó0 */ - case '\n': - if ( - dd->mly >= 0 /* n¥ý¿ï¤l */ - && - dd->brd[dd->mly][dd->mlx].color != dd->brd[dd->my][dd->mx].color /* ¦P¦â¤£¯à²¾°Ê¤]¤£¯à¦Y */ - && - (Is_move(dd, dd->my, dd->mx, dd->mly, dd->mlx) || - Is_win(dd, dd->brd[dd->mly][dd->mlx], dd->brd[dd->my][dd->mx], dd->my, dd->mx, dd->mly, dd->mlx)) - ) { - if (dd->fix && dd->brd[dd->my][dd->mx].value < 0) { - *b = -1; - return 0; - } - if (dd->brd[dd->my][dd->mx].value >= 0 && dd->brd[dd->my][dd->mx].die == 0) { - if (!color) - dd->bcount--; - else - dd->rcount--; - move(dd->cur_eaty, dd->cur_eatx); - if(color) - outs(bname[dd->brd[dd->my][dd->mx].value]); - else - outs(rname[dd->brd[dd->my][dd->mx].value]); - if (dd->cur_eatx >= 26) { - dd->cur_eatx = 5; - dd->cur_eaty++; - } else - dd->cur_eatx += 3; - } - brdswap(dd, dd->my, dd->mx, dd->mly, dd->mlx); - draw_line(dd, dd->mly, -1); - draw_line(dd, dd->my, -1); - if (dd->fix == 1) - *b = -1; - else { - dd->mly = -1; - dd->mlx = -1; - *b = 0; - } - } else - *b = -1; - break; - default: - *b = -1; - } - - if (!dd->rcount) - return -1; - else if (!dd->bcount) - return -1; - if (*b == -1) - return 0; - dd->curr.y = dd->my; - dd->curr.x = dd->mx; - dd->curr.end = (!*b) ? 1 : 0; - send(fd, &dd->curr, sizeof(dd->curr), 0); - send(fd, &dd->brd, sizeof(dd->brd), 0); - return 0; -} - -int -main_dark(int fd, userinfo_t * uin) -{ - sint end = 0, ch = 1, i = 0; - char buf[16]; - struct DarkData dd; - - memset(&dd, 0, sizeof(dd)); - dd.my=dd.mx=0; - dd.mly=dd.mlx=-1; - - *buf = 0; - dd.fix = 0; - currutmp->color = '.'; - /* '.' ªí¥ÜÁÙ¨S¨M©wÃC¦â */ - dd.rcount = 16; - dd.bcount = 16; - //initialize - dd.cur_eaty = 18, dd.cur_eatx = 5; - setutmpmode(DARK); - brd_prints(); - if (currutmp->turn) { - brd_rand(&dd); - send(fd, &dd.brd, sizeof(dd.brd), 0); - mouts(21, 0, " " ANSI_COLOR(1;37) ANSI_COLOR(1;33) "¡»" ANSI_COLOR(1;37) "§A¬O¥ý¤â" ANSI_RESET); - mouts(22, 0, " " ANSI_COLOR(1;33) "¡»" ANSI_COLOR(5;35) "½ü¨ì§A¤U¤F" ANSI_RESET); - } else { - recv(fd, &dd.brd, sizeof(dd.brd), 0); - mouts(21, 0, " " ANSI_COLOR(1;33) "¡»" ANSI_COLOR(1;37) "§A¬O«á¤â" ANSI_RESET); - } - move(12, 3); - prints("%s[0³Ó0±Ñ]" ANSI_COLOR(5;31) "¢þ¢û" ANSI_COLOR(1;37) "." ANSI_RESET "%s[0³Ó0±Ñ]", currutmp->userid, currutmp->mateid); - outs("\n" - " " ANSI_COLOR(1;36) "¢®¢¬" ANSI_COLOR(1;31) "¥\\¯àªí" ANSI_COLOR(1;36) "¢¢®¢¢¬¢®¢" ANSI_RESET "\n" - " " ANSI_COLOR(1;36) "¢¬" ANSI_COLOR(1;33) " ¡ô¡ö¡õ¡÷" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) "²¾°Ê" ANSI_RESET "\n" - " " ANSI_COLOR(1;36) "¢®" ANSI_COLOR(1;33) " ¢û" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) " ¿ï¤l,½¤l" ANSI_RESET "\n" - " " ANSI_COLOR(1;36) "¢¬" ANSI_COLOR(1;33) " enter" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) " ¦Y´Ñ,©ñ´Ñ" ANSI_RESET "\n" - "¡@" ANSI_COLOR(1;33) "¤w¸g¸Ñ¨Mªº" ANSI_COLOR(1;37) ":" ANSI_COLOR(1;36) "¡@¡@ ¢®" ANSI_COLOR(1;33) " ¢ø" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) " ¦X´Ñ" ANSI_RESET "\n" - " ¡@¡@ " ANSI_COLOR(1;36) "¢¬" ANSI_COLOR(1;33) " ¢ù" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) " »{¿é" ANSI_RESET "\n" - " " ANSI_COLOR(1;36) "¢®" ANSI_COLOR(1;33) " ¢ë" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) " ´«Ãä" ANSI_RESET); - - if (currutmp->turn) - move(cury[0], curx[0]); - - add_io(fd, 0); - while (end <= 0) { - if (uin->turn == 'w' || currutmp->turn == 'w') { - end = -1; - break; - } - ch = igetch(); - if (ch == I_OTHERDATA) { - ch = recv(fd, &dd.curr, sizeof(dd.curr), 0); - if (ch != sizeof(dd.curr)) { - if (uin->turn == 'e') { - end = -3; - break; - } else if (uin->turn != 'w') { - end = -1; - currutmp->turn = 'w'; - break; - } - end = -1; - break; - } - if (dd.curr.end == -3) - mouts(23, 30, ANSI_COLOR(33) "n¨D¦X´Ñ" ANSI_RESET); - else if (dd.curr.end == -4) - mouts(23, 30, ANSI_COLOR(33) "n¨D´«Ãä" ANSI_RESET); - else if (dd.curr.end == -5) - mouts(23, 30, ANSI_COLOR(33) "n¨D³s¦Y" ANSI_RESET); - else - mouts(23, 30, ""); - - recv(fd, &dd.brd, sizeof(dd.brd), 0); - dd.my = dd.curr.y; - dd.mx = dd.curr.x; - redraw(&dd); - if (dd.curr.end) - mouts(22, 0, " " ANSI_COLOR(1;33) "¡»" ANSI_COLOR(5;35) "½ü¨ì§A¤U¤F" ANSI_RESET); - move(cury[dd.my], curx[dd.mx]); - } else { - if (currutmp->turn == 'p') { - if (ch == 'y') { - end = -3; - currutmp->turn = 'e'; - break; - } else { - mouts(23, 30, ""); - *buf = 0; - currutmp->turn = (uin->turn) ? 0 : 1; - } - } else if (currutmp->turn == 'c') { - if (ch == 'y') { - currutmp->color = (currutmp->color == '1') ? '0' : '1'; - uin->color = (uin->color == '1') ? '0' : '1'; - mouts(21, 0, (currutmp->color == '1') ? " " ANSI_COLOR(1;33) "¡»" ANSI_COLOR(1;31) "§A«ù¬õ¦â´Ñ" ANSI_RESET : " " ANSI_COLOR(1;33) "¡»" ANSI_COLOR(1;36) "§A«ù¶Â¦â´Ñ" ANSI_RESET); - } else { - mouts(23, 30, ""); - currutmp->turn = (uin->turn) ? 0 : 1; - } - } else if (currutmp->turn == 'g') { - if (ch == 'y') { - dd.cont = 1; - mouts(21, 0, " " ANSI_COLOR(1;33) "¡»" ANSI_COLOR(1;31) "§A«ù¬õ¦â´Ñ" ANSI_RESET " ¥i³s¦Y"); - } else { - mouts(23, 30, ""); - currutmp->turn = (uin->turn) ? 0 : 1; - } - } - if (currutmp->turn == 1) { - sint go_on = 0; - if (uin->turn == 'g') { - dd.cont = 1; - uin->turn = (currutmp->turn) ? 0 : 1; - mouts(21, 10, "¥i³s¦Y"); - } - end = playing(&dd, fd, currutmp->color - '0', ch, &go_on, uin); - - if (end == -1) { - currutmp->turn = 'w'; - break; - } else if (end == -2) { - uin->turn = 'w'; - break; - } else if (end == -3) { - uin->turn = 'p'; - dd.curr.end = -3; - send(fd, &dd.curr, sizeof(dd.curr), 0); - send(fd, &dd.brd, sizeof(buf), 0); - continue; - } else if (end == -4) { - if (currutmp->color != '1' && currutmp->color != '0') - continue; - uin->turn = 'c'; - i = 0; - dd.curr.end = -4; - send(fd, &dd.curr, sizeof(dd.curr), 0); - send(fd, &dd.brd, sizeof(buf), 0); - continue; - } else if (end == -5) { - uin->turn = 'g'; - dd.curr.end = -5; - send(fd, &dd.curr, sizeof(dd.curr), 0); - send(fd, &dd.brd, sizeof(buf), 0); - continue; - } - if (!i && currutmp->color == '1') { - mouts(21, 0, " " ANSI_COLOR(1;33) "¡»" ANSI_COLOR(1;31) "§A«ù¬õ¦â´Ñ" ANSI_RESET); - i++; - move(cury[dd.my], curx[dd.mx]); - } - if (!i && currutmp->color == '0') { - mouts(21, 0, " " ANSI_COLOR(1;33) "¡»" ANSI_COLOR(1;36) "§A«ù¶Â¦â´Ñ" ANSI_RESET); - i++; - move(cury[dd.my], curx[dd.mx]); - } - if (uin->turn == 'e') { - end = -3; - break; - } - if (go_on < 0) - continue; - - move(22, 0); - clrtoeol(); - prints(" " ANSI_COLOR(1;33) "¡»" ANSI_COLOR(1;37) "½ü¨ì%s¤U §O©È§O©È ¥LºâÔ£¦Ì" ANSI_RESET, currutmp->mateid); - currutmp->turn = 0; - uin->turn = 1; - } else { - if (ch == 'q') { - uin->turn = 'w'; - break; - } - move(22, 0); - clrtoeol(); - prints(" " ANSI_COLOR(1;33) "¡»" ANSI_COLOR(1;37) "½ü¨ì%s¤U §O©È§O©È ¥LºâÔ£¦Ì" ANSI_RESET, currutmp->mateid); - } - } - } - - switch (end) { - case -1: - case -2: - if (currutmp->turn == 'w') { - move(22, 0); - clrtoeol(); - outs(ANSI_COLOR(1;31) "§AŤF.. ¯u¬O®¥³ß~~" ANSI_RESET); - } else { - move(22, 0); - clrtoeol(); - outs(ANSI_COLOR(1;31) "¿é±¼¤F°Õ.....¤U¦¸Åý¥L¦n¬Ý!!" ANSI_RESET); - } - break; - case -3: - mouts(22, 0, ANSI_COLOR(1;31) "¦X´Ñò!! ¤U¦¸¦b¤À°ª¤U§a ^_^" ANSI_RESET); - break; - default: - add_io(0, 0); - close(fd); - pressanykey(); - return 0; - } - add_io(0, 0); - close(fd); - pressanykey(); - return 0; -} diff --git a/mbbsd/edit.c b/mbbsd/edit.c deleted file mode 100644 index c6b3a544..00000000 --- a/mbbsd/edit.c +++ /dev/null @@ -1,3886 +0,0 @@ -/* $Id$ */ -/** - * edit.c, ¥Î¨Ó´£¨Ñ bbs¤Wªº¤å¦r½s¿è¾¹, §Y ve. - * ²{¦b³o¤@Ó¬O´c·d¹Lªºª©¥», ¤ñ¸û¤£Ã©w, ¥Î¤ñ¸û¦hªº cpu, ¦ý¬O¥i¥H¬Ù¤U³\¦h - * ªº°O¾ÐÅé (¥H Ptt¬°¨Ò, ¦b¤E¤d¤H¤W¯¸ªº®ÉÔ, ¬ù¥i¬Ù¤U 50MB ªº°O¾ÐÅé) - * ¦pªG±z»{¬°¡u®³ cpu´«°O¾ÐÅé¡v¨Ã¤£¦X¥G±zªº¶·¨D, ±z¥i¥H¦Ò¼{§ï¨Ï¥Î×¥¿«eªº - * ª©¥» (Revision 782) - * - * 쥻 ve ªº°µªk¬O, ¦]¬°¨C¤@¦æ³Ì¤j¥i¥H¿é¤J WRAPMARGIN Ó¦r, ©ó¬O´N´À¨C¤@ - * ¦æ«O¯d¤F WRAPMARGIN ³o»ò¤jªºªÅ¶¡ (¬ù 512 bytes) . ¦ý¬O¹ê»Ú¤W, ¯¸¦b×¥¿ - * ¦¨¥»³Ì¤pªº¦Ò¶q¤W, §ÚÌ¥u¶·n¨Ï±o´å¼Ð©Ò¦b³o¤@¦æºû«ù WRAPMARGIN ³o»ò¤j, - * ¨ä¥L¨C¤@¦æ¨ä¹ê¤£¶·n³o»ò¦hªºªÅ¶¡. ©ó¬O³oÓ patch´N¦b¨C¦¸´å¼Ð¦b¦æ¶¡²¾°Ê - * ªº®ÉÔ, ±N쥻ªº¨º¦æ°O¾ÐÅéÁY¤p, ¦A±N·s²¾¨ìªº¨º¦æ«·s¥[¤j, ¥H¹F¦¨³Ì¤pªº - * °O¾ÐÅé¥Î¶q. - * ¥H¤W»¡ªº³oӰʧ@¦b adjustline() ¤¤§¹¦¨, adjustline()¥t¥~¥]¬A×¥¿¼ÆÓ - * global pointer, ¥HÁקK dangling pointer . - * ¥t¥~Y©w¸q DEBUG, ¦b textline_t µ²ºc¤¤±N¥[¤J mlength, ªí¥Ü¸Ó¦æ¹ê»Ú¦ûªº - * °O¾ÐÅé¤j¤p. ¥H¤è«K´ú¸Õµ²ªG. - * ³oÓª©¥»¦ü¥GÁÙ¦³¦a¤è¨S¦³×¥¿¦n, ¥i¯à¾ÉP segmentation fault . - * - * FIXME ¦b°Ï¶ô¼Ð°O¼Ò¦¡(blockln>=0)¤¤¹ï¼W§Rקï¥i¯à·|³y¦¨ blockln, blockpnt, - * and/or blockline ¿ù»~. ¬Æ¦Ü§â blockline ¬å±¼·| access ¨ì¤w³Q free ±¼ªº - * memory. ¥i¯àn§ï¦¨¼Ð°O¼Ò¦¡ readonly, ©Î¬O°µ¬Y¨Ç°Ê§@®É¦Û°Ê¨ú®ø¼Ð°O¼Ò¦¡ - * (blockln=-1) - * - * FIXME 20071201 piaip - * block selection ¤£ª¾¦ó®É¤wÅܬ° line level ¦Ó«D character level ¤F¡A - * ³o¼Ë¤]¤ñ¸û¦n¼g¡A©Ò¥H§â blockpnt ®³±¼§a¡I - * - * 20071230 piaip - * BBSmovie ¦³¤H§@¥X¤F 1.9G ªºÀÉ®×, ¬Ý¨Ón¤À hard limit ¸ò soft limit - * [²Ä 7426572/7426572 ¶ (100%) ¥Ø«eÅã¥Ü: ²Ä 163384551~163384573 ¦æ] - * ·í¤é½Õ¬d BBSmovie ¬ÝªO»PºëµØ°Ï¡A¥§¡Àɮ׬Ҧb 5M ¥H¤U - * ³Ì¤jªº¬° 16M ªº Haruhi OP (avi ÂàÀÉ with massive ANSI) - * [²Ä 2953/2953 ¶ (100%) ¥Ø«eÅã¥Ü: ²Ä 64942~64964 ¦æ] - * ¥t¥~¤¬°Ê°g®cªº¤j¤p¬° - * [²Ä 1408/1408 ¶ (100%) ¥Ø«eÅã¥Ü: ²Ä 30940~30962 ¦æ] - * ¬O¥H©w¸q: - * 32M ¬° size limit - * 1M ¬° line limit - * ¤S¡A©¿µMµo²{¤§«e totaln ¤§Ãþ³£¬O short... ©Ò¥H 65536 ´N°÷¤F? - * «áµù: ¦ü¥G¬O¥Î announce ªº append §@¥X¨Óªº¡A¦³¬Ý¨ì > --- <- mark¡C - */ -#include "bbs.h" - -#define EDIT_SIZE_LIMIT (32768*1024) -#define EDIT_LINE_LIMIT (65530) // (1048576) - -#if 0 -#define register -#define DEBUG -#define inline -#endif - -/** - * data Äæ¦ìªº¥Îªk: - * ¨C¦¸ allocate ¤@Ó textline_t ®É¡A·|°tµ¹¥L (sizeof(textline_t) + string - * length - 1) ªº¤j¤p¡C¦p¦¹¥iª½±µ¦s¨ú data ¦Ó¤£»ÝÃB¥~ªº malloc¡C - */ -typedef struct textline_t { - struct textline_t *prev; - struct textline_t *next; - short len; -#ifdef DEBUG - short mlength; -#endif - char data[1]; -} textline_t; - -#define KEEP_EDITING -2 - -enum { - NOBODY, MANAGER, SYSOP -}; - - -/** - * ³oÓ»¡©ú·|±N¾ãÓ edit.c ¹B§@ªº·§©À±a¹L¡A¥Dn·|±q editor_internal_t ªº - * data structure ½Í°_¡C¹ï©ó¨C¤@Ó data member ªº¸Ô²Ó¥\¯à¡A½Ð¨£ sturcture - * ¤¤ªºµù¸Ñ¡C - * - * ¤å³¹ªº¤º®e (¥H¤UºÙ content) ¥H¡u¦æ¡v¬°³æ¦ì¡A¥Dn¥H firstline, lastline, - * totaln ¨Ó°O¿ý¡C - * - * User ¦bµe±¤¤¬Ý¨ìªºµe±¡A¸m©ó¤@Ó¡u window ¡v¤¤¡A³oÓ window ·|¦b - * content ¤W²¾°Ê¡Awindow ¸Ì±ªº½d³ò§Y¬°n show ¥X¨Óªº½d³ò¡C¥¦¥Î¤F¤£¤Ö - * Äæ¦ì¨Ó°O¿ý¡A¥]¬A currline, top_of_win, currln, currpnt, curr_window_line, - * edit_margin¡CÅã¥Ü¥X¨Óªº®ÄªG·íµM¤£¥u¬O¾a³o´XÓ¸ê®Æ¡AÁÙ·|¸ò¨ä¥LÄæ¦ì¦³¥æ¤¬ - * §@¥Î¡A¨Ò¦p ±m¦â½s¿è¼Ò¦¡¡B¯S®í²Å¸¹½s¿è µ¥µ¥¡C¨ä¤¤³Ì½ÆÂøªº³¡¤À¬O¦b¿ï¨ú block - * ¡]¨£«á¡^ªº®ÉÔ¡C¤ñ¸û¤£ª½Ä±ªº¦æ¬°¬O¡G°£«D´å¼Ð¦b¶}©l¿ï¨ú¸ò¥Ø«e¡]µ²§ô¡^ªº¦ì¸m - * ¬O¦P¤@Ó¡]¦¹®É³oÓ½d³ò¬O¿ï¨úªº½d³ò¡^¡A§_«h´N¬O±q¶}©l¨º¤@¦C¤@ª½¨ì¥Ø«e¡]µ²§ô¡^ - * ³o¤@¦C¡C - * - * editor ªº¨Ï¥Î¤W¥Ø«e¦³¤ºØ inclusive ªº mode¡G - * insert mode: - * ´¡¤J/¨ú¥N - * ansi mode: - * ±m¦â½s¿è - * indent mode: - * ¦Û°ÊÁY±Æ - * phone mode: - * ¯S®í²Å¸¹½s¿è - * raw mode: - * ignore Ctrl('S'), Ctrl('Q'), Ctrl('T') - * ÃÙ¤ê: ³o¦³¤°»ò¥Î? ¬Ý°_¨Ó¬O modem ¤W¶Ç¥Î (¨S¤H¦b¥Î³oÓ¤F§a) - * ®³¨Ó·í dbcs option §a - * - * editor ¤ä´©¤F°Ï¶ô¿ï¾Üªº¥\¯à¡]¦h¦æ¿ï¨ú ©Î ³æ¦æ¤¤ªº¤ù¬q¡^¡A¹ï©ó¤@Ó selected - * block¡A¥i¥H cut, copy, cancel, ©ÎªÌ¦s¨ì¼È¨úÀÉ¡A¬Æ¦Ü¬O©¹¥ª/¥k shift¡C¸Ô¨£ - * block_XXX¡C - * - * ¥Î Ctrl('Y') §R°£ªº¨º¤@¦æ·|³Q°O¨ì deleted_line ³oÓÄæ¦ì¤¤¡Cundelete_line() - * ¥i¥H°µ undelete ªº°Ê§@¡C deleted_line ªì©lȬ° NULL¡A¨C¦¸¥u¤¹³\¦s¤@¦æ¡A©Ò¥H - * ¦b¦s¤U¨Ó®É¡Aµo²{Ȥ£¬° NULL ·|¥ý°µ free ªº°Ê§@¡Ceditor µ²§ô®É¡A¦b - * edit_buffer_destructor() ¤¤¦pªGµo²{¦³ deleted_line¡A·|¦b³oÃäÄÀ©ñ±¼¡C¨ä¥L¦a - * ¤è¤]¦³¬Û¦Pªº§@ªk¡A¨Ò¦p searched_string¡Csearched_string ¬O¦b·j´M¤å³¹¤º®e - * ®É¡An´M§äªº key word¡C - * - * ÁÙ¦³¤@Ó¦³½ìªº¯SÂI¡A¡u¬A¸¹¤Ç°t¡v¡I¦æ¬°´N¦p¦P¦b vim ¸Ì±¤@¼Ë¡C§c¡A·íµM¨S¨º - * »ò±j°Õ¡A¦ý¦Ü¤Ö¦b§t¦³ c-style comment ¸ò c-style string ®É¬O¹ïªº³á¡C³oÓ°Ê - * §@©w¸q©ó match_paren() ¤¤¡C - * - * ¥t¥~¡A¦pªG¦³»Ýn·s¼W·sªºÄæ¦ì¡A½Ð±Nªì©l¤Æ¡]¦³»Ýnªº¸Ü¡^ªº°Ê§@¼g¦b - * edit_buffer_constructor ¤¤¡C·íµM¤]¦³Ó edit_buffer_destructor ¥i¥H¨Ï¥Î¡C - * - * ¦¹¥~¡A¬°¤F´£¨Ñ¤@Ó reentrant ªº editor¡Aprev «ü¦V«e¤@Ó editor ªº - * editor_internal_t¡Center_edit_buffer ¸ò exit_edit_buffer ´£¨Ñ¶i¥Xªº¤¶±¡A - * ¸Ì±¤À§O·|©I¥s constructor ¸ò destructor¡C - * - * TODO - * vedit ¸Ì±¦³Ó curr_buf->oldcurrline¡A¥Î¨Ó°O¤W¤@¦¸ªº currline¡C¥Ñ©ó¥u¦³ currline ¾Ö - * ¦³ WRAPMARGIN ªºªÅ¶¡¡A©Ò¥H¥Ø«eªº§@ªk¬O·í curr_buf->oldcurrline != currline ®É¡A´N - * resize curr_buf->oldcurrline ¸ò currline¡C¦ý¬OÁV¿|ªº¬O¥Ø«e¥²¶·¤H¤u°lÂÜ currline ªº¦æ - * ¬°¡A¦Ó¥BY¤£©¯¹J¨ì curr_buf->oldcurrline «ü¨ìªº¨º¤@¦æ¤w¸g³Q free ±¼¡A´N§¹¤F¡C³Ì¦n¬O - * §â³o¨ÇªF¦è¥]°_¨Ó¡C¤£¹L§Ú¨SªÅ°µ¤F¡Apatch is welcome :P - * - * Victor Hsieh <victor@csie.org> - * Thu, 03 Feb 2005 15:18:00 +0800 - */ -typedef struct editor_internal_t { - - textline_t *firstline; /* first line of the article. */ - textline_t *lastline; /* last line of the article. */ - - textline_t *currline; /* current line of the article(window). */ - textline_t *blockline; /* the first selected line of the block. */ - textline_t *top_of_win; /* top line of the article in the window. */ - - textline_t *deleted_line; /* deleted line. Just keep one deleted line. */ - textline_t *oldcurrline; - - int currln; /* current line of the article. */ - short currpnt; /* current column of the article. */ - int totaln; /* total lines of the article. */ - int curr_window_line; /* current line to the window. */ - short last_margin; - short edit_margin; /* when the cursor moves out of range (say, - t_columns), shift this length of the string - so you won't see the first edit_margin-th - character. */ - short lastindent; - int blockln; /* the row you started to select block. */ - char insert_c; /* insert this character when shift something - in order to compensate the new space. */ - char last_phone_mode; - - char ifuseanony :1; - char redraw_everything :1; - - char insert_mode :1; - char ansimode :1; - char indent_mode :1; - char phone_mode :1; - char raw_mode :1; - - char *searched_string; - char *sitesig_string; - char *(*substr_fp) (); - - char synparser; // syntax parser - - struct editor_internal_t *prev; - -} editor_internal_t; -// } __attribute__ ((packed)) - -static editor_internal_t *curr_buf = NULL; - -static const char fp_bak[] = "bak"; - -static const char * const BIG5[13] = { - "¡A¡F¡G¡B¡N¡C¡H¡I¡E¡T¡]¡^¡©¡ª¡«¡¬", - "¢b¢c¢d¢e¢f¢g¢h¢i¢j¢k¢l¢m¢n¢o¢pùþ ", - "¡³¡ó¡·¡´¡¸¡¹¡¼¡½¡¿¡¶¡¾¡µ¡º¡»¡ð¡ñ", - "¡Ë¡\\¡[¡Â¡Ä¡X¡ü¡ý¢y¡þ¢@¢®¢¬¢¢A¢B", - "¡Ï¡Ð¡Ñ¡Ò¡Ô¡Ó¡×¡Ý¡Ú¡Ü¡Ø¡Ù¡Õ¡Ö¡î¡ï", - "¡Û¡ã¡ä¡å¡ì¡í¡®¡æ¡ç¡è¡é¡Þ¡ß¡à¡á¡â", - "¡ô¡õ¡ö¡÷¡ø¡ù¡ú¡û", - "¡i¡j¡u¡v¡y¡z¡q¡r¡m¡n¡e¡f¡a¡b¡_¡`", - "¡g¡h¡c¡d¡k¡l¡s¡t¡o¡p¡w¡x¡{¡|", - "¢¨¢©¢ª¢«¡Î¡¯¡°¡±¢I¡ò¡À¡K¡L¡Æ¡È", - "£\\£]£^£_£`£a£b£c£d£e£f£g£h£i£j£k", - "£l£m£n£o£p£q£r£s£G£K£N£S£U£X£Z£[", - "¢¹¢º¢»¢¼¢½¢¾¢¿¢À¢Á¢Â" -}; - -static const char * const BIG_mode[13] = { - "¼ÐÂI", - "¹Ï¶ô", - "¼Ð°O", - "¼Ð½u", - "¼Æ¤@", - "¼Æ¤G", - "½bÀY", - "¬A¤@", - "¬A¤G", - "¨ä¥L", - "§Æ¤@", - "§Æ¤G", - "¼Æ¦r" -}; - -static const char *table[8] = { - "¢x¢w¢|¢r¢}¢u¢q¢t¢z¢s¢{", - "ùø¢¤ùãùäùåùàùáùâùÝùÞùß", - "ùø¢wùõùöù÷ùòùóùôùïùðùñ", - "¢x¢¤ùìùíù¢¦¢§ùæùçùè", - "¢x¢w¢¢¢r¢£¢u¢q¢t¢~¢s¢¡", - "ùø¢¤¢¢ù䢣ùàùáùâ¢~ùÞ¢¡", - "ùø¢wùõùöù÷ùòùóùôùïùðùñ", - "¢x¢¤ùìùíù¢¦¢§ùæùçùè" -}; - -static const char *table_mode[6] = { - "ª½¨¤", - "Ås©·", - "¢q", - "ùá", - "ùó", - "¢¦" -}; - -#ifdef DBCSAWARE -static char mbcs_mode =1; - -#define IS_BIG5_HI(x) (0x81 <= (x) && (x) <= 0xfe) -#define IS_BIG5_LOS(x) (0x40 <= (x) && (x) <= 0x7e) -#define IS_BIG5_LOE(x) (0x80 <= (x) && (x) <= 0xfe) -#define IS_BIG5_LO(x) (IS_BIG5_LOS(x) || IS_BIG5_LOE(x)) -#define IS_BIG5(hi,lo) (IS_BIG5_HI(hi) && IS_BIG5_LO(lo)) - -int mchar_len(unsigned char *str) -{ - return ((str[0] != '\0' && str[1] != '\0' && IS_BIG5(str[0], str[1])) ? - 2 : - 1); -} - -#define FC_RIGHT (0) -#define FC_LEFT (~FC_RIGHT) - -int fix_cursor(char *str, int pos, unsigned int dir) -{ - int newpos, w; - - for(newpos = 0; - *str != '\0' && - (w = mchar_len((unsigned char*)str), - newpos + 1 + (dir & (w - 1))) <= pos; - str += w, newpos += w) - ; - - return newpos; -} - -#endif - -/* °O¾ÐÅéºÞ²z»P½s¿è³B²z */ -static void -indigestion(int i) -{ - vmsgf("ÄY«¤º¶Ë (%d)\n", i); - u_exit("EDITOR FAILED"); - assert(0); - exit(0); -} - -static inline void -edit_buffer_constructor(editor_internal_t *buf) -{ - /* all unspecified columns are 0 */ - buf->blockln = -1; - buf->insert_c = ' '; - buf->insert_mode = 1; - buf->redraw_everything = 1; - buf->lastindent = -1; -} - -static inline void -enter_edit_buffer(void) -{ - editor_internal_t *p = curr_buf; - curr_buf = (editor_internal_t *)malloc(sizeof(editor_internal_t)); - memset(curr_buf, 0, sizeof(editor_internal_t)); - curr_buf->prev = p; - edit_buffer_constructor(curr_buf); -} - -static inline void -free_line(textline_t *p) -{ - p->next = (textline_t*)0x12345678; - p->prev = (textline_t*)0x87654321; - p->len = -12345; - free(p); -} - -static inline void -edit_buffer_destructor(void) -{ - if (curr_buf->deleted_line != NULL) - free_line(curr_buf->deleted_line); - - if (curr_buf->searched_string != NULL) - free(curr_buf->searched_string); - if (curr_buf->sitesig_string != NULL) - free(curr_buf->sitesig_string); -} - -static inline void -exit_edit_buffer(void) -{ - editor_internal_t *p = curr_buf; - - edit_buffer_destructor(); - curr_buf = p->prev; - free(p); -} - -/** - * transform position ansix in an ansi string of textline_t to the same - * string without escape code. - * @return position in the string without escape code. - */ -static int -ansi2n(int ansix, textline_t * line) -{ - register char *data, *tmp; - register char ch; - - data = tmp = line->data; - - while (*tmp) { - if (*tmp == KEY_ESC) { - while ((ch = *tmp) && !isalpha((int)ch)) - tmp++; - if (ch) - tmp++; - continue; - } - if (ansix <= 0) - break; - tmp++; - ansix--; - } - return tmp - data; -} - -/** - * opposite to ansi2n, according to given textline_t. - * @return position in the string with escape code. - */ -static short -n2ansi(short nx, textline_t * line) -{ - register short ansix = 0; - register char *tmp, *nxp; - register char ch; - - tmp = nxp = line->data; - nxp += nx; - - while (*tmp) { - if (*tmp == KEY_ESC) { - while ((ch = *tmp) && !isalpha((int)ch)) - tmp++; - if (ch) - tmp++; - continue; - } - if (tmp >= nxp) - break; - tmp++; - ansix++; - } - return ansix; -} - -/* ¿Ã¹õ³B²z¡G»²§U°T®§¡BÅã¥Ü½s¿è¤º®e */ - -static inline void -show_phone_mode_panel(void) -{ - int i; - - move(b_lines - 1, 0); - clrtoeol(); - - if (curr_buf->last_phone_mode < 20) { - int len; - prints(ANSI_COLOR(1;46) "¡i%s¿é¤J¡j ", BIG_mode[curr_buf->last_phone_mode - 1]); - len = strlen(BIG5[curr_buf->last_phone_mode - 1]) / 2; - for (i = 0; i < len; i++) - prints(ANSI_COLOR(37) "%c" ANSI_COLOR(34) "%2.2s", - i + 'A', BIG5[curr_buf->last_phone_mode - 1] + i * 2); - for (i = 0; i < 16 - len; i++) - outs(" "); - outs(ANSI_COLOR(37) " `1~9-=¤Á´« Zªí®æ" ANSI_RESET); - } - else { - prints(ANSI_COLOR(1;46) "¡iªí®æø»s¡j /=%s *=%s§Î ", - table_mode[(curr_buf->last_phone_mode - 20) / 4], - table_mode[(curr_buf->last_phone_mode - 20) % 4 + 2]); - for (i = 0;i < 11;i++) - prints(ANSI_COLOR(37) "%c" ANSI_COLOR(34) "%2.2s", i ? i + '/' : '.', - table[curr_buf->last_phone_mode - 20] + i * 2); - outs(ANSI_COLOR(37) " Z¤º½X " ANSI_RESET); - } -} - -/** - * Show the bottom status/help bar, and BIG5/table in phone_mode. - */ -static void -edit_msg(void) -{ - int n = curr_buf->currpnt; - - if (curr_buf->ansimode) /* Thor: §@ ansi ½s¿è */ - n = n2ansi(n, curr_buf->currline); - - if (curr_buf->phone_mode) - show_phone_mode_panel(); - - move(b_lines, 0); - clrtoeol(); - outs( ANSI_COLOR(37;44) " ½s¿è¤å³¹ " - ANSI_COLOR(31;47) " (^Z/F1)" ANSI_COLOR(30) "»¡©ú " - ANSI_COLOR(31;47) "(^P/^G)" ANSI_COLOR(30) "´¡¤J²Å¸¹/¹Ï¤ù " - ANSI_COLOR(31) "(^X/^Q)" ANSI_COLOR(30) "Â÷¶}"); - - prints( "ùø%s¢x%c%c%c%cùø %3d:%3d ", - curr_buf->insert_mode ? "´¡¤J" : "¨ú¥N", - curr_buf->ansimode ? 'A' : 'a', - curr_buf->indent_mode ? 'I' : 'i', - curr_buf->phone_mode ? 'P' : 'p', - curr_buf->raw_mode ? 'R' : 'r', - curr_buf->currln + 1, n + 1); - outslr("", 78, ANSI_RESET, 0); -} - -/** - * return the middle line of the window. - */ -static inline int -middle_line(void) -{ - return p_lines / 2 + 1; -} - -/** - * Return the previous 'num' line. Stop at the first line if there's - * not enough lines. - */ -static textline_t * -back_line(textline_t * pos, int num) -{ - while (num-- > 0) { - register textline_t *item; - - if (pos && (item = pos->prev)) { - pos = item; - curr_buf->currln--; - } - else - break; - } - return pos; -} - -/* calculate if cursor is at bottom, scroll required? - * currently vedit does NOT handle if curr_window_line > b_lines, - * take care if you changed curr_window_line! - */ -static inline int -cursor_at_bottom_line(void) -{ - return curr_buf->curr_window_line == b_lines || - (curr_buf->phone_mode && curr_buf->curr_window_line == b_lines - 1); -} - - -/** - * Return the next 'num' line. Stop at the last line if there's not - * enough lines. - */ -static textline_t * -forward_line(textline_t * pos, int num) -{ - while (num-- > 0) { - register textline_t *item; - - if (pos && (item = pos->next)) { - pos = item; - curr_buf->currln++; - } - else - break; - } - return pos; -} - -/** - * move the cursor to the next line with ansimode fixed. - */ -static inline void -cursor_to_next_line(void) -{ - short pos; - - if (curr_buf->currline->next == NULL) - return; - - curr_buf->currline = curr_buf->currline->next; - curr_buf->curr_window_line++; - curr_buf->currln++; - - if (curr_buf->ansimode) { - pos = n2ansi(curr_buf->currpnt, curr_buf->currline->prev); - curr_buf->currpnt = ansi2n(pos, curr_buf->currline); - } - else { - curr_buf->currpnt = (curr_buf->currline->len > curr_buf->lastindent) - ? curr_buf->lastindent : curr_buf->currline->len; - } -} - -/** - * opposite to cursor_to_next_line. - */ -static inline void -cursor_to_prev_line(void) -{ - short pos; - - if (curr_buf->currline->prev == NULL) - return; - - curr_buf->curr_window_line--; - curr_buf->currln--; - curr_buf->currline = curr_buf->currline->prev; - - if (curr_buf->ansimode) { - pos = n2ansi(curr_buf->currpnt, curr_buf->currline->next); - curr_buf->currpnt = ansi2n(pos, curr_buf->currline); - } - else { - curr_buf->currpnt = (curr_buf->currline->len > curr_buf->lastindent) - ? curr_buf->lastindent : curr_buf->currline->len; - } -} - -static inline void -window_scroll_down(void) -{ - curr_buf->curr_window_line = 0; - - if (!curr_buf->top_of_win->prev) - indigestion(6); - else { - curr_buf->top_of_win = curr_buf->top_of_win->prev; - rscroll(); - } -} - -static inline void -window_scroll_up(void) -{ - curr_buf->curr_window_line = b_lines - (curr_buf->phone_mode ? 2 : 1); - - if (unlikely(!curr_buf->top_of_win->next)) - indigestion(7); - else { - curr_buf->top_of_win = curr_buf->top_of_win->next; - if(curr_buf->phone_mode) - move(b_lines-1, 0); - else - move(b_lines, 0); - clrtoeol(); - scroll(); - } -} - -/** - * Get the current line number in the window now. - */ -static int -get_lineno_in_window(void) -{ - int cnt = 0; - textline_t *p = curr_buf->currline; - - while (p && (p != curr_buf->top_of_win)) { - cnt++; - p = p->prev; - } - return cnt; -} - -/** - * shift given raw data s with length len to left by one byte. - */ -static void -raw_shift_left(char *s, int len) -{ - int i; - for (i = 0; i < len && s[i] != 0; ++i) - s[i] = s[i + 1]; -} - -/** - * shift given raw data s with length len to right by one byte. - */ -static void -raw_shift_right(char *s, int len) -{ - int i; - for (i = len - 1; i >= 0; --i) - s[i + 1] = s[i]; -} - -/** - * Return the pointer to the next non-space position. - */ -static char * -next_non_space_char(char *s) -{ - while (*s == ' ') - s++; - return s; -} - -/** - * allocate a textline_t with length length. - */ -static textline_t * -alloc_line(short length) -{ - textline_t *p; - - if ((p = (textline_t *) malloc(length + sizeof(textline_t)))) { - memset(p, 0, length + sizeof(textline_t)); -#ifdef DEBUG - p->mlength = length; -#endif - return p; - } - indigestion(13); - abort_bbs(0); - return NULL; -} - -/** - * Insert p after line in list. Keeps up with last line - */ -static void -insert_line(textline_t *line, textline_t *p) -{ - textline_t *n; - - if ((p->next = n = line->next)) - n->prev = p; - else - curr_buf->lastline = p; - line->next = p; - p->prev = line; -} - -/** - * delete_line deletes 'line' from the line list. - * @param saved true if you want to keep the line in deleted_line - */ -static void -delete_line(textline_t * line, int saved) -{ - register textline_t *p = line->prev; - register textline_t *n = line->next; - - if (!p && !n) { - line->data[0] = line->len = 0; - return; - } - assert(line != curr_buf->top_of_win); - if (n) - n->prev = p; - else - curr_buf->lastline = p; - if (p) - p->next = n; - else - curr_buf->firstline = n; - - curr_buf->totaln--; - - if (saved) { - if (curr_buf->deleted_line != NULL) - free_line(curr_buf->deleted_line); - curr_buf->deleted_line = line; - curr_buf->deleted_line->next = NULL; - curr_buf->deleted_line->prev = NULL; - } - else { - free_line(line); - } -} - -/** - * Return the indent space number according to CURRENT line and the FORMER - * line. It'll be the first line contains non-space character. - * @return space number from the beginning to the first non-space character, - * return 0 if non or not in indent mode. - */ -static int -indent_space(void) -{ - textline_t *p; - int spcs; - - if (!curr_buf->indent_mode) - return 0; - - for (p = curr_buf->currline; p; p = p->prev) { - for (spcs = 0; p->data[spcs] == ' '; ++spcs); - /* empty loop */ - if (p->data[spcs]) - return spcs; - } - return 0; -} - -/** - * adjustline(oldp, len); - * ¥Î¨Ó±N oldp «ü¨ìªº¨º¤@¦æ, «·s×¥¿¦¨ len³o»òªø. - * - * ©I¥s¤F adjustline «á°O±oÀˬd¦³°Ê¨ì currline, ¦pªG¬Oªº¸Ü oldcurrline ¤]n°Ê - * - * In FreeBSD: - * ¦b³oÃä¤@¦@°µ¤F¨â¦¸ªº memcpy() , ²Ä¤@¦¸±q heap «þ¨ì stack , - * §âì¨Ó°O¾ÐÅé free() «á, ¤S«·s¦b stack¤W malloc() ¤@¦¸, - * µM«á¦A«þ¨©¦^¨Ó. - * ¥Dn¬O¥Î sbrk() Æ[¹î¨ìªºµ²ªG, ³o¼Ë¤l¤~¯uªº¯àÁY´î°O¾ÐÅé¥Î¶q. - * ¸Ô¨£ /usr/share/doc/papers/malloc.ascii.gz (in FreeBSD) - */ -static textline_t * -adjustline(textline_t *oldp, short len) -{ - // XXX write a generic version ? - char tmpl[sizeof(textline_t) + WRAPMARGIN]; - textline_t *newp; - -#ifdef deBUG - if(oldp->len > WRAPMARGIN || oldp->len < 0) { - kill(currpid, SIGSEGV); - } -#endif - - memcpy(tmpl, oldp, oldp->len + sizeof(textline_t)); - free_line(oldp); - - newp = alloc_line(len); - memcpy(newp, tmpl, len + sizeof(textline_t)); -#ifdef DEBUG - newp->mlength = len; -#endif - if( oldp == curr_buf->firstline ) curr_buf->firstline = newp; - if( oldp == curr_buf->lastline ) curr_buf->lastline = newp; - if( oldp == curr_buf->currline ) curr_buf->currline = newp; - if( oldp == curr_buf->blockline ) curr_buf->blockline = newp; - if( oldp == curr_buf->top_of_win) curr_buf->top_of_win= newp; - if( newp->prev != NULL ) newp->prev->next = newp; - if( newp->next != NULL ) newp->next->prev = newp; - // vmsg("adjust %x to %x, length: %d", (int)oldp, (int)newp, len); - return newp; -} - -/** - * split 'line' right before the character pos - * - * @return the latter line after splitting - */ -static textline_t * -split(textline_t * line, int pos) -{ - if (pos <= line->len) { - register textline_t *p = alloc_line(WRAPMARGIN); - register char *ptr; - int spcs = indent_space(); - - curr_buf->totaln++; - - p->len = line->len - pos + spcs; - line->len = pos; - - memset(p->data, ' ', spcs); - p->data[spcs] = 0; - - ptr = line->data + pos; - if (curr_buf->indent_mode) - ptr = next_non_space_char(ptr); - strcat(p->data + spcs, ptr); - ptr[0] = '\0'; - - if (line == curr_buf->currline && pos <= curr_buf->currpnt) { - line = adjustline(line, line->len); - insert_line(line, p); - // because p is allocated with fullsize, we can skip adjust. - // curr_buf->oldcurrline = line; - curr_buf->oldcurrline = curr_buf->currline = p; - if (pos == curr_buf->currpnt) - curr_buf->currpnt = spcs; - else - curr_buf->currpnt -= pos; - curr_buf->curr_window_line++; - curr_buf->currln++; - - /* split may cause cursor hit bottom */ - if (cursor_at_bottom_line()) - window_scroll_up(); - } else { - p = adjustline(p, p->len); - insert_line(line, p); - } - curr_buf->redraw_everything = YEA; - } - return line; -} - -/** - * Insert a character ch to current line. - * - * The line will be split if the length is >= WRAPMARGIN. It'll be split - * from the last space if any, or start a new line after the last character. - */ -static void -insert_char(int ch) -{ - register textline_t *p = curr_buf->currline; - register int i = p->len; - register char *s; - int wordwrap = YEA; - - if (curr_buf->currpnt > i) { - indigestion(1); - return; - } - if (curr_buf->currpnt < i && !curr_buf->insert_mode) { - p->data[curr_buf->currpnt++] = ch; - /* Thor: ansi ½s¿è, ¥i¥Hoverwrite, ¤£»\¨ì ansi code */ - if (curr_buf->ansimode) - curr_buf->currpnt = ansi2n(n2ansi(curr_buf->currpnt, p), p); - } else { - raw_shift_right(p->data + curr_buf->currpnt, i - curr_buf->currpnt + 1); - p->data[curr_buf->currpnt++] = ch; - i = ++(p->len); - } - if (i < WRAPMARGIN) - return; - s = p->data + (i - 1); - while (s != p->data && *s == ' ') - s--; - while (s != p->data && *s != ' ') - s--; - if (s == p->data) { - wordwrap = NA; - s = p->data + (i - 2); - } - p = split(p, (s - p->data) + 1); - p = p->next; - i = p->len; - if (wordwrap && i >= 1) { - if (p->data[i - 1] != ' ') { - p->data[i] = ' '; - p->data[i + 1] = '\0'; - p->len++; - } - } -} - -/** - * insert_char twice. - */ -static void -insert_dchar(const char *dchar) -{ - insert_char(*dchar); - insert_char(*(dchar+1)); -} - -static void -insert_tab(void) -{ - do { - insert_char(' '); - } while (curr_buf->currpnt & 0x7); -} - -/** - * Insert a string. - * - * All printable and ESC_CHR will be directly printed out. - * '\t' will be printed to align every 8 byte. - * '\n' will split the line. - * The other character will be ignore. - */ -static void -insert_string(const char *str) -{ - char ch; - - while ((ch = *str++)) { - if (isprint2(ch) || ch == ESC_CHR) - insert_char(ch); - else if (ch == '\t') - insert_tab(); - else if (ch == '\n') - split(curr_buf->currline, curr_buf->currpnt); - } -} - -/** - * undelete the deleted line. - * - * return NULL if there's no deleted_line, otherwise, return currline. - */ -static textline_t * -undelete_line(void) -{ - editor_internal_t tmp; - - if (!curr_buf->deleted_line) - return NULL; - - tmp.top_of_win = curr_buf->top_of_win; - tmp.indent_mode = curr_buf->indent_mode; - tmp.curr_window_line = curr_buf->curr_window_line; - - curr_buf->indent_mode = 0; - curr_buf->currpnt = 0; - curr_buf->currln++; - insert_string(curr_buf->deleted_line->data); - insert_string("\n"); - - curr_buf->top_of_win = tmp.top_of_win; - curr_buf->indent_mode = tmp.indent_mode; - curr_buf->curr_window_line = tmp.curr_window_line; - - assert(curr_buf->currline->prev); - curr_buf->currline = adjustline(curr_buf->currline, curr_buf->currline->len); - curr_buf->currline = curr_buf->currline->prev; - curr_buf->currline = adjustline(curr_buf->currline, WRAPMARGIN); - curr_buf->oldcurrline = curr_buf->currline; - - if (curr_buf->currline->prev == NULL) { - curr_buf->top_of_win = curr_buf->currline; - curr_buf->currln = 0; - } - return curr_buf->currline; -} - -/* - * join $line and $line->next - * - * line: A1 A2 - * next: B1 B2 - * ....: C1 C2 - * - * case B=empty: - * return YEA - * - * case A+B < WRAPMARGIN: - * line: A1 A2 B1 B2 - * next: C1 C2 - * return YEA - * NOTE It assumes $line has allocated WRAPMARGIN length of data buffer. - * - * case A+B1+B2 > WRAPMARGIN, A+B1<WRAPMARGIN - * line: A1 A2 B1 - * next: B2 " " - * call join($next) - */ -static int -join(textline_t * line) -{ - register textline_t *n; - register int ovfl; - - if (!(n = line->next)) - return YEA; - if (!*next_non_space_char(n->data)) - return YEA; - - ovfl = line->len + n->len - WRAPMARGIN; - if (ovfl < 0) { - strcat(line->data, n->data); - line->len += n->len; - delete_line(n, 0); - return YEA; - } else { - register char *s; /* the split point */ - - s = n->data + n->len - ovfl - 1; - while (s != n->data && *s == ' ') - s--; - while (s != n->data && *s != ' ') - s--; - if (s == n->data) - return YEA; - split(n, (s - n->data) + 1); - if (line->len + line->next->len >= WRAPMARGIN) { - indigestion(0); - return YEA; - } - join(line); - n = line->next; - ovfl = n->len - 1; - if (ovfl >= 0 && ovfl < WRAPMARGIN - 2) { - s = &(n->data[ovfl]); - if (*s != ' ') { - strcpy(s, " "); - n->len++; - } - } - line->next=adjustline(line->next, WRAPMARGIN); - join(line->next); - line->next=adjustline(line->next, line->next->len); - return NA; - } -} - -static void -delete_char(void) -{ - register int len; - - if ((len = curr_buf->currline->len)) { - if (unlikely(curr_buf->currpnt >= len)) { - indigestion(1); - return; - } - raw_shift_left(curr_buf->currline->data + curr_buf->currpnt, curr_buf->currline->len - curr_buf->currpnt + 1); - curr_buf->currline->len--; - } -} - -static void -load_file(FILE * fp, off_t offSig) -{ - char buf[WRAPMARGIN + 2]; - int indent_mode0 = curr_buf->indent_mode; - size_t szread = 0; - - assert(fp); - curr_buf->indent_mode = 0; - while (fgets(buf, sizeof(buf), fp)) - { - szread += strlen(buf); - if (offSig < 0 || szread <= offSig) - { - insert_string(buf); - } - else - { - // this is the site sig - break; - } - } - curr_buf->indent_mode = indent_mode0; -} - -/* ¼È¦sÀÉ */ -char * -ask_tmpbuf(int y) -{ - static char fp_buf[10] = "buf.0"; - static char msg[] = "½Ð¿ï¾Ü¼È¦sÀÉ (0-9)[0]: "; - - msg[19] = fp_buf[4]; - do { - if (!getdata(y, 0, msg, fp_buf + 4, 4, DOECHO)) - fp_buf[4] = msg[19]; - } while (fp_buf[4] < '0' || fp_buf[4] > '9'); - return fp_buf; -} - -static void -read_tmpbuf(int n) -{ - FILE *fp; - char fp_tmpbuf[80]; - char tmpfname[] = "buf.0"; - char *tmpf; - char ans[4] = "y"; - - if (curr_buf->totaln >= EDIT_LINE_LIMIT) - { - vmsg("Àɮפw¶W¹L³Ì¤j¨î¡AµLªk¦AŪ¤J¼È¦sÀÉ¡C"); - return; - } - - if (0 <= n && n <= 9) { - tmpfname[4] = '0' + n; - tmpf = tmpfname; - } else { - tmpf = ask_tmpbuf(3); - n = tmpf[4] - '0'; - } - - setuserfile(fp_tmpbuf, tmpf); - if (n != 0 && n != 5 && more(fp_tmpbuf, NA) != -1) - getdata(b_lines - 1, 0, "½T©wŪ¤J¶Ü(Y/N)?[Y]", ans, sizeof(ans), LCECHO); - if (*ans != 'n' && (fp = fopen(fp_tmpbuf, "r"))) { - load_file(fp, -1); - fclose(fp); - while (curr_buf->curr_window_line >= b_lines) { - curr_buf->curr_window_line--; - curr_buf->top_of_win = curr_buf->top_of_win->next; - } - } -} - -static void -write_tmpbuf(void) -{ - FILE *fp; - char fp_tmpbuf[80], ans[4]; - textline_t *p; - off_t sz = 0; - - setuserfile(fp_tmpbuf, ask_tmpbuf(3)); - if (dashf(fp_tmpbuf)) { - more(fp_tmpbuf, NA); - getdata(b_lines - 1, 0, "¼È¦sÀɤw¦³¸ê®Æ (A)ªþ¥[ (W)Âмg (Q)¨ú®ø¡H[A] ", - ans, sizeof(ans), LCECHO); - - if (ans[0] == 'q') - return; - } - if (ans[0] != 'w') // 'a' - { - sz = dashs(fp_tmpbuf); - if (sz > EDIT_SIZE_LIMIT) - { - vmsg("¼È¦sÀɤw¶W¹L¤j¤p¨î¡AµLªk¦Aªþ¥[¡C"); - return; - } - } - if ((fp = fopen(fp_tmpbuf, (ans[0] == 'w' ? "w" : "a+")))) { - for (p = curr_buf->firstline; p; p = p->next) { - if (p->next || p->data[0]) - fprintf(fp, "%s\n", p->data); - } - fclose(fp); - } -} - -static void -erase_tmpbuf(void) -{ - char fp_tmpbuf[80]; - char ans[4] = "n"; - - setuserfile(fp_tmpbuf, ask_tmpbuf(3)); - if (more(fp_tmpbuf, NA) != -1) - getdata(b_lines - 1, 0, "½T©w§R°£¶Ü(Y/N)?[N]", - ans, sizeof(ans), LCECHO); - if (*ans == 'y') - unlink(fp_tmpbuf); -} - -/** - * ½s¿è¾¹¦Û°Ê³Æ¥÷ - *(³Ì¦h³Æ¥÷ 512 ¦æ (?)) - */ -void -auto_backup(void) -{ - if (curr_buf == NULL) - return; - - if (curr_buf->currline) { - FILE *fp; - textline_t *p, *v; - char bakfile[PATHLEN]; - int count = 0; - - setuserfile(bakfile, fp_bak); - if ((fp = fopen(bakfile, "w"))) { - for (p = curr_buf->firstline; p != NULL && count < 512; p = v, count++) { - v = p->next; - fprintf(fp, "%s\n", p->data); - free_line(p); - } - fclose(fp); - } - curr_buf->currline = NULL; - } -} - -/** - * ¨ú¦^½s¿è¾¹³Æ¥÷ - */ -void -restore_backup(void) -{ - char bakfile[80], buf[80]; - - setuserfile(bakfile, fp_bak); - if (dashf(bakfile)) { - stand_title("½s¿è¾¹¦Û°Ê´_ì"); - getdata(1, 0, "±z¦³¤@½g¤å³¹©|¥¼§¹¦¨¡A(S)¼g¤J¼È¦sÀÉ (Q)ºâ¤F¡H[S] ", - buf, 4, LCECHO); - if (buf[0] != 'q') { - setuserfile(buf, ask_tmpbuf(3)); - Rename(bakfile, buf); - } else - unlink(bakfile); - } -} - -/* ¤Þ¥Î¤å³¹ */ - -static int -garbage_line(const char *str) -{ - int qlevel = 0; - - while (*str == ':' || *str == '>') { - if (*(++str) == ' ') - str++; - if (qlevel++ >= 1) - return 1; - } - while (*str == ' ' || *str == '\t') - str++; - if (qlevel >= 1) { - if (!strncmp(str, "¡° ", 3) || !strncmp(str, "==>", 3) || - strstr(str, ") ´£¨ì:\n")) - return 1; - } - return (*str == '\n'); -} - -static void -quote_strip_ansi_inline(unsigned char *is) -{ - unsigned char *os = is; - - while (*is) - { - if(*is != ESC_CHR) - *os++ = *is; - else - { - is ++; - if(*is == '*') - { - /* ptt prints, keep it as normal */ - *os++ = '*'; - *os++ = '*'; - } - else - { - /* normal ansi, strip them out. */ - while (*is && ANSI_IN_ESCAPE(*is)) - is++; - } - } - is++; - - } - - *os = 0; -} - -static void -do_quote(void) -{ - int op; - char buf[512]; - - getdata(b_lines - 1, 0, "½Ð°Ýn¤Þ¥Îì¤å¶Ü(Y/N/All/Repost)¡H[Y] ", - buf, 3, LCECHO); - op = buf[0]; - - if (op != 'n') { - FILE *inf; - - if ((inf = fopen(quote_file, "r"))) { - char *ptr; - int indent_mode0 = curr_buf->indent_mode; - - fgets(buf, sizeof(buf), inf); - if ((ptr = strrchr(buf, ')'))) - ptr[1] = '\0'; - else if ((ptr = strrchr(buf, '\n'))) - ptr[0] = '\0'; - - if ((ptr = strchr(buf, ':'))) { - char *str; - - while (*(++ptr) == ' '); - - /* ¶¶¤â²o¦Ï¡A¨ú±o author's address */ - if ((curredit & EDIT_BOTH) && (str = strchr(quote_user, '.'))) { - strcpy(++str, ptr); - str = strchr(str, ' '); - assert(str); - str[0] = '\0'; - } - } else - ptr = quote_user; - - curr_buf->indent_mode = 0; - insert_string("¡° ¤Þz¡m"); - insert_string(ptr); - insert_string("¡n¤§»Ê¨¥¡G\n"); - - if (op != 'a') /* ¥h±¼ header */ - while (fgets(buf, sizeof(buf), inf) && buf[0] != '\n'); - /* FIXME by MH: - ¦pªG header ¨ì¤º¤å¤¤¶¡¨S¦³ªÅ¦æ¤À¹j¡A·|³y¦¨ All ¥H¥~ªº¼Ò¦¡ - ³£¤Þ¤£¨ì¤º¤å¡C - */ - - if (op == 'a') - while (fgets(buf, sizeof(buf), inf)) { - insert_char(':'); - insert_char(' '); - quote_strip_ansi_inline((unsigned char *)buf); - insert_string(buf); - } - else if (op == 'r') - while (fgets(buf, sizeof(buf), inf)) { - /* repost, keep anything */ - // quote_strip_ansi_inline((unsigned char *)buf); - insert_string(buf); - } - else { - if (curredit & EDIT_LIST) /* ¥h±¼ mail list ¤§ header */ - while (fgets(buf, sizeof(buf), inf) && (!strncmp(buf, "¡° ", 3))); - while (fgets(buf, sizeof(buf), inf)) { - if (!strcmp(buf, "--\n")) - break; - if (!garbage_line(buf)) { - insert_char(':'); - insert_char(' '); - quote_strip_ansi_inline((unsigned char *)buf); - insert_string(buf); - } - } - } - curr_buf->indent_mode = indent_mode0; - fclose(inf); - } - } -} - -/** - * ¼f¬d user ¤Þ¨¥ªº¨Ï¥Î - */ -static int -check_quote(void) -{ - register textline_t *p = curr_buf->firstline; - register char *str; - int post_line; - int included_line; - - post_line = included_line = 0; - while (p) { - if (!strcmp(str = p->data, "--")) - break; - if (str[1] == ' ' && ((str[0] == ':') || (str[0] == '>'))) - included_line++; - else { - while (*str == ' ' || *str == '\t') - str++; - if (*str) - post_line++; - } - p = p->next; - } - - if ((included_line >> 2) > post_line) { - move(4, 0); - outs("¥»½g¤å³¹ªº¤Þ¨¥¤ñ¨Ò¶W¹L 80%¡A½Ð±z°µ¨Ç·Lªº×¥¿¡G\n\n" - ANSI_COLOR(1;33) "1) ¼W¥[¤@¨Ç¤å³¹ ©Î 2) §R°£¤£¥²n¤§¤Þ¨¥" ANSI_RESET); - { - char ans[4]; - - getdata(12, 12, "(E)Ä~Äò½s¿è (W)±j¨î¼g¤J¡H[E] ", - ans, sizeof(ans), LCECHO); - if (ans[0] == 'w') - return 0; - } - return 1; - } - return 0; -} - -/* Àɮ׳B²z¡GŪÀÉ¡B¦sÀÉ¡B¼ÐÃD¡Bñ¦WÀÉ */ -off_t loadsitesig(const char *fname); - -static void -read_file(const char *fpath, int splitSig) -{ - FILE *fp; - off_t offSig = -1; - - if (splitSig) - offSig = loadsitesig(fpath); - - if ((fp = fopen(fpath, "r")) == NULL) { - int fd; - if ((fd = creat(fpath, 0600)) >= 0) { - close(fd); - return; - } - indigestion(4); - abort_bbs(0); - } - load_file(fp, offSig); - fclose(fp); -} - -void -write_header(FILE * fp, char *mytitle) // FIXME unused -{ - - if (curredit & EDIT_MAIL || curredit & EDIT_LIST) { - fprintf(fp, "%s %s (%s)\n", str_author1, cuser.userid, - cuser.nickname - ); - } else { - char *ptr = mytitle; - struct { - char author[IDLEN + 1]; - char board[IDLEN + 1]; - char title[66]; - time4_t date; /* last post's date */ - int number; /* post number */ - } postlog; - - memset(&postlog, 0, sizeof(postlog)); - strlcpy(postlog.author, cuser.userid, sizeof(postlog.author)); - if (curr_buf) - curr_buf->ifuseanony = 0; -#ifdef HAVE_ANONYMOUS - if (currbrdattr & BRD_ANONYMOUS) { - int defanony = (currbrdattr & BRD_DEFAULTANONYMOUS); - if (defanony) - getdata(3, 0, "½Ð¿é¤J§A·Q¥ÎªºID¡A¤]¥iª½±µ«ö[Enter]¡A" - "©Î¬O«ö[r]¥Î¯u¦W¡G", real_name, sizeof(real_name), DOECHO); - else - getdata(3, 0, "½Ð¿é¤J§A·Q¥ÎªºID¡A¤]¥iª½±µ«ö[Enter]¨Ï¥ÎìID¡G", - real_name, sizeof(real_name), DOECHO); - if (!real_name[0] && defanony) { - strlcpy(real_name, "Anonymous", sizeof(real_name)); - strlcpy(postlog.author, real_name, sizeof(postlog.author)); - if (curr_buf) - curr_buf->ifuseanony = 1; - } else { - if (!strcmp("r", real_name) || (!defanony && !real_name[0])) - strlcpy(postlog.author, cuser.userid, sizeof(postlog.author)); - else { - snprintf(postlog.author, sizeof(postlog.author), - "%s.", real_name); - if (curr_buf) - curr_buf->ifuseanony = 1; - } - } - } -#endif - strlcpy(postlog.board, currboard, sizeof(postlog.board)); - if (!strncmp(ptr, str_reply, 4)) - ptr += 4; - strlcpy(postlog.title, ptr, sizeof(postlog.title)); - postlog.date = now; - postlog.number = 1; - append_record(".post", (fileheader_t *) & postlog, sizeof(postlog)); -#ifdef HAVE_ANONYMOUS - if (currbrdattr & BRD_ANONYMOUS) { - int defanony = (currbrdattr & BRD_DEFAULTANONYMOUS); - - fprintf(fp, "%s %s (%s) %s %s\n", str_author1, postlog.author, - (((!strcmp(real_name, "r") && defanony) || - (!real_name[0] && (!defanony))) ? cuser.nickname : - "²q²q§Ú¬O½Ö ? ^o^"), - local_article ? str_post2 : str_post1, currboard); - } else { - fprintf(fp, "%s %s (%s) %s %s\n", str_author1, cuser.userid, - cuser.nickname, - local_article ? str_post2 : str_post1, currboard); - } -#else /* HAVE_ANONYMOUS */ - fprintf(fp, "%s %s (%s) %s %s\n", str_author1, cuser.userid, - cuser.nickname, - local_article ? str_post2 : str_post1, currboard); -#endif /* HAVE_ANONYMOUS */ - - } - mytitle[72] = '\0'; - fprintf(fp, "¼ÐÃD: %s\n®É¶¡: %s\n", mytitle, ctime4(&now)); -} - -off_t -loadsitesig(const char *fname) -{ - int fd = 0; - off_t sz = 0, ret = -1; - char *start, *sp; - - sz = dashs(fname); - if (sz < 1) - return -1; - fd = open(fname, O_RDONLY); - if (fd < 0) - return -1; - start = (char*)mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); - if (start) - { - sp = start + sz - 4 - 1; // 4 = \n--\n - while (sp > start) - { - if ((*sp == '\n' && strncmp(sp, "\n--\n", 4) == 0) || - (*sp == '\r' && strncmp(sp, "\r--\r", 4) == 0) ) - { - size_t szSig = sz - (sp-start+1); - ret = sp - start + 1; - // allocate string - curr_buf->sitesig_string = (char*) malloc (szSig + 1); - if (curr_buf->sitesig_string) - { - memcpy(curr_buf->sitesig_string, sp+1, szSig); - curr_buf->sitesig_string[szSig] = 0; - } - break; - } - sp --; - } - munmap(start, sz); - } - - close(fd); - return ret; -} - -void -addsignature(FILE * fp, int ifuseanony) -{ - FILE *fs; - int i; - char buf[WRAPMARGIN + 1]; - char fpath[STRLEN]; - - char ch; - - if (!strcmp(cuser.userid, STR_GUEST)) { - fprintf(fp, "\n--\n¡° µo«H¯¸ :" BBSNAME "(" MYHOSTNAME - ") \n¡» From: %s\n", fromhost); - return; - } - if (!ifuseanony) { - - int browsing = 0; - SigInfo si; - memset(&si, 0, sizeof(si)); - -browse_sigs: - showsignature(fpath, &i, &si); - - if (si.total > 0){ - char msg[64]; - - ch = isdigit(cuser.signature) ? cuser.signature : 'x'; - sprintf(msg, - (browsing || (si.max > si.show_max)) ? - "½Ð¿ï¾Üñ¦WÀÉ (1-9, 0=¤£¥[ n=½¶ x=ÀH¾÷)[%c]: ": - "½Ð¿ï¾Üñ¦WÀÉ (1-9, 0=¤£¥[ x=ÀH¾÷)[%c]: ", - ch); - getdata(0, 0, msg, buf, 4, LCECHO); - - if(buf[0] == 'n') - { - si.show_start = si.show_max + 1; - if(si.show_start > si.max) - si.show_start = 0; - browsing = 1; - goto browse_sigs; - } - - if (!buf[0]) - buf[0] = ch; - - if (isdigit((int)buf[0])) - ch = buf[0]; - else - ch = '1' + random() % (si.max+1); - cuser.signature = buf[0]; - - if (ch != '0') { - fpath[i] = ch; - do - { - if ((fs = fopen(fpath, "r"))) { - fputs("\n--\n", fp); - for (i = 0; i < MAX_SIGLINES && - fgets(buf, sizeof(buf), fs); i++) - fputs(buf, fp); - fclose(fs); - fpath[i] = ch; - } - else - fpath[i] = '1' + (fpath[i] - '1' + 1) % (si.max+1); - } while (!isdigit((int)buf[0]) && si.max > 0 && ch != fpath[i]); - } - } - } -#ifdef HAVE_ORIGIN -#ifdef HAVE_ANONYMOUS - if (ifuseanony) - fprintf(fp, "\n--\n¡° µo«H¯¸: " BBSNAME "(" MYHOSTNAME - ") \n¡» From: %s\n", "°Î¦W¤Ñ¨Ïªº®a"); - else -#endif - { - char temp[33]; - - strlcpy(temp, fromhost, sizeof(temp)); - fprintf(fp, "\n--\n¡° µo«H¯¸: " BBSNAME "(" MYHOSTNAME - ") \n¡» From: %s\n", temp); - } -#endif -} - -#ifdef EXP_EDIT_UPLOAD -static void upload_file(void); -#endif // EXP_EDIT_UPLOAD - -static int -write_file(char *fpath, int saveheader, int *islocal, char *mytitle, int upload, int chtitle) -{ - struct tm *ptime; - FILE *fp = NULL; - textline_t *p, *v; - char ans[TTLEN], *msg; - int aborted = 0, line = 0, checksum[3], sum = 0, po = 1; - - stand_title("Àɮ׳B²z"); - move(1,0); - -#ifdef EDIT_UPLOAD_ALLOWALL - upload = 1; -#endif // EDIT_UPLOAD_ALLOWALL - - // common trail - - if (currstat == SMAIL) - outs("[S]Àx¦s"); - else if (local_article) - outs("[L]¯¸¤º«H¥ó (S)Àx¦s"); - else - outs("[S]Àx¦s (L)¯¸¤º«H¥ó"); - -#ifdef EXP_EDIT_UPLOAD - if (upload) - outs(" (U)¤W¶Ç¸ê®Æ"); -#endif // EXP_EDIT_UPLOAD - - if (chtitle) - outs(" (T)§ï¼ÐÃD"); - - outs(" (A)©ñ±ó (E)Ä~Äò (R/W/D)Ū¼g§R¼È¦sÀÉ"); - - getdata(2, 0, "½T©wnÀx¦sÀɮ׶ܡH ", ans, 2, LCECHO); - - // avoid lots pots - sleep(1); - - switch (ans[0]) { - case 'a': - outs("¤å³¹" ANSI_COLOR(1) " ¨S¦³ " ANSI_RESET "¦s¤J"); - aborted = -1; - break; - case 'e': - return KEEP_EDITING; -#ifdef EXP_EDIT_UPLOAD - case 'u': - if (upload) - upload_file(); - return KEEP_EDITING; -#endif // EXP_EDIT_UPLOAD - case 'r': - read_tmpbuf(-1); - return KEEP_EDITING; - case 'w': - write_tmpbuf(); - return KEEP_EDITING; - case 'd': - erase_tmpbuf(); - return KEEP_EDITING; - case 't': - if (!chtitle) - return KEEP_EDITING; - move(3, 0); - prints("¼ÐÃD¡G%s", mytitle); - strlcpy(ans, mytitle, sizeof(ans)); - if (getdata_buf(4, 0, "·s¼ÐÃD¡G", ans, sizeof(ans), DOECHO)) - strlcpy(mytitle, ans, STRLEN); - return KEEP_EDITING; - case 's': - if (!HasUserPerm(PERM_LOGINOK)) { - local_article = 1; - move(2, 0); - outs("±z©|¥¼³q¹L¨¥÷½T»{¡A¥u¯à Local Save¡C\n"); - pressanykey(); - } else - local_article = 0; - break; - case 'l': - local_article = 1; - } - - if (!aborted) { - - if (saveheader && !(curredit & EDIT_MAIL) && check_quote()) - return KEEP_EDITING; - - if (!(*fpath)) - setuserfile(fpath, "ve_XXXXXX"); - if ((fp = fopen(fpath, "w")) == NULL) { - indigestion(5); - abort_bbs(0); - } - if (saveheader) - write_header(fp, mytitle); - } - for (p = curr_buf->firstline; p; p = v) { - v = p->next; - if (!aborted) { - assert(fp); - msg = p->data; - if (v || msg[0]) { - trim(msg); - - line++; - - /* check crosspost */ - if (currstat == POSTING && po ) { - int msgsum = StringHash(msg); - if (msgsum) { - if (postrecord.last_bid != currbid && - postrecord.checksum[po] == msgsum) { - po++; - if (po > 3) { - postrecord.times++; - postrecord.last_bid = currbid; - po = 0; - } - } else - po = 1; - if (line >= curr_buf->totaln / 2 && sum < 3) { - checksum[sum++] = msgsum; - } - } - } - fprintf(fp, "%s\n", msg); - } - } - free_line(p); - } - curr_buf->currline = NULL; - - // what if currbid == 0? add currstat checking. - if (currstat == POSTING && - postrecord.times > MAX_CROSSNUM-1 && - !is_hidden_board_friend(currbid, currutmp->uid)) - anticrosspost(); - - if (po && sum == 3) { - memcpy(&postrecord.checksum[1], checksum, sizeof(int) * 3); - if(postrecord.last_bid != currbid) - postrecord.times = 0; - } - - if (aborted) - return aborted; - - if (islocal) - *islocal = local_article; - - if (curr_buf->sitesig_string) - fprintf(fp, curr_buf->sitesig_string); - - if (currstat == POSTING || currstat == SMAIL) - { - addsignature(fp, curr_buf->ifuseanony); - } - else if (currstat == REEDIT) - { -#ifndef ALL_REEDIT_LOG - // why force signature in SYSOP board? - if(strcmp(currboard, GLOBAL_SYSOP) == 0) -#endif - { - ptime = localtime4(&now); - fprintf(fp, - "¡° ½s¿è: %-15s ¨Ó¦Û: %-20s (%02d/%02d %02d:%02d)\n", - cuser.userid, fromhost, - ptime->tm_mon + 1, ptime->tm_mday, - ptime->tm_hour, ptime->tm_min); - } - } - - fclose(fp); - return 0; -} - -static inline int -has_block_selection(void) -{ - return curr_buf->blockln >= 0; -} - -/** - * a block is continual lines of the article. - */ - -/** - * stop the block selection. - */ -static void -block_cancel(void) -{ - if (has_block_selection()) { - curr_buf->blockln = -1; - curr_buf->redraw_everything = YEA; - } -} - -static inline void -setup_block_begin_end(textline_t **begin, textline_t **end) -{ - if (curr_buf->currln >= curr_buf->blockln) { - *begin = curr_buf->blockline; - *end = curr_buf->currline; - } else { - *begin = curr_buf->currline; - *end = curr_buf->blockline; - } -} - -#define BLOCK_TRUNCATE 0 -#define BLOCK_APPEND 1 -/** - * save the selected block to file 'fname.' - * mode: BLOCK_TRUNCATE truncate mode - * BLOCK_APPEND append mode - */ -static void -block_save_to_file(const char *fname, int mode) -{ - textline_t *begin, *end; - char fp_tmpbuf[80]; - FILE *fp; - - if (!has_block_selection()) - return; - - setup_block_begin_end(&begin, &end); - - setuserfile(fp_tmpbuf, fname); - if ((fp = fopen(fp_tmpbuf, mode == BLOCK_APPEND ? "a+" : "w+"))) { - - textline_t *p; - - for (p = begin; p != end; p = p->next) - fprintf(fp, "%s\n", p->data); - fprintf(fp, "%s\n", end->data); - fclose(fp); - } -} - -/** - * delete selected block - */ -static void -block_delete(void) -{ - textline_t *begin, *end; - textline_t *p; - - if (!has_block_selection()) - return; - - setup_block_begin_end(&begin, &end); - - // the block region is (currln, block) or (blockln, currln). - - if (curr_buf->currln > curr_buf->blockln) { - // case (blockln, currln) - // piaip 2007/1201 ¦b³o¸Ì즳 offset-by-one issue - // ¦pªG¤S¹J¨ì¡A½ÐÀˬd³oªþªñ¡C - curr_buf->curr_window_line -= (curr_buf->currln - curr_buf->blockln); - - if (curr_buf->curr_window_line <= 0) { - curr_buf->curr_window_line = 0; - if (end->next) - (curr_buf->top_of_win = end->next)->prev = begin->prev; - else - curr_buf->top_of_win = (curr_buf->lastline = begin->prev); - } - curr_buf->currln -= (curr_buf->currln - curr_buf->blockln); - } else { - // case (currln, blockln) - } - - // adjust buffer after delete - if (begin->prev) - begin->prev->next = end->next; - else if (end->next) - curr_buf->top_of_win = curr_buf->firstline = end->next; - else { - curr_buf->currline = curr_buf->top_of_win = curr_buf->firstline = curr_buf->lastline = alloc_line(WRAPMARGIN); - curr_buf->currln = curr_buf->curr_window_line = curr_buf->edit_margin = 0; - } - - // adjust current line - if (end->next) { - curr_buf->currline = end->next; - curr_buf->currline->prev = begin->prev; - } - else if (begin->prev) { - curr_buf->currline = (curr_buf->lastline = begin->prev); - curr_buf->currln--; - if (curr_buf->curr_window_line > 0) - curr_buf->curr_window_line--; - } - - // remove buffer - for (p = begin; p != end; curr_buf->totaln--) - free_line((p = p->next)->prev); - - free_line(end); - curr_buf->totaln--; - - curr_buf->currpnt = 0; -} - -static void -block_cut(void) -{ - if (!has_block_selection()) - return; - - block_save_to_file("buf.0", BLOCK_TRUNCATE); - block_delete(); - - curr_buf->blockln = -1; - curr_buf->redraw_everything = YEA; -} - -static void -block_copy(void) -{ - if (!has_block_selection()) - return; - - block_save_to_file("buf.0", BLOCK_TRUNCATE); - - curr_buf->blockln = -1; - curr_buf->redraw_everything = YEA; -} - -static void -block_prompt(void) -{ - char fp_tmpbuf[80]; - char tmpfname[] = "buf.0"; - char mode[2]; - - move(b_lines - 1, 0); - clrtoeol(); - - if (!getdata(b_lines - 1, 0, "§â°Ï¶ô²¾¦Ü¼È¦sÀÉ (0:Cut, 5:Copy, 6-9, q: Cancel)[0] ", tmpfname + 4, 4, LCECHO)) - tmpfname[4] = '0'; - - if (tmpfname[4] < '0' || tmpfname[4] > '9') - goto cancel_block; - - if (tmpfname[4] == '0') { - block_cut(); - return; - } - else if (tmpfname[4] == '5') { - block_copy(); - return; - } - - setuserfile(fp_tmpbuf, tmpfname); - if (dashf(fp_tmpbuf)) { - more(fp_tmpbuf, NA); - getdata(b_lines - 1, 0, "¼È¦sÀɤw¦³¸ê®Æ (A)ªþ¥[ (W)Âмg (Q)¨ú®ø¡H[W] ", mode, sizeof(mode), LCECHO); - if (mode[0] == 'q') - goto cancel_block; - else if (mode[0] != 'a') - mode[0] = 'w'; - } - - if (getans("§R°£°Ï¶ô(Y/N)?[N] ") != 'y') - goto cancel_block; - - block_save_to_file(tmpfname, mode[0] == 'a' ? BLOCK_APPEND : BLOCK_TRUNCATE); - -cancel_block: - curr_buf->blockln = -1; - curr_buf->redraw_everything = YEA; -} - -static void -block_select(void) -{ - curr_buf->blockln = curr_buf->currln; - curr_buf->blockline = curr_buf->currline; -} - -enum { - EOATTR_NORMAL = 0x00, - EOATTR_SELECTED = 0x01, // selected (reverse) - EOATTR_MOVIECODE= 0x02, // pmore movie - EOATTR_BBSLUA = 0x04, // BBS Lua (header) - EOATTR_COMMENT = 0x08, // comment syntax - -}; - -static const char *luaKeywords[] = { - "and", "break", "do", "else", "elseif", - "end", "for", "if", "in", "not", "or", - "repeat","return","then","until","while", - NULL -}; - -static const char *luaDataKeywords[] = { - "false", "function", "local", "nil", "true", - NULL -}; - -static const char *luaFunctions[] = { - "assert", "print", "tonumber", "tostring", "type", - NULL -}; - -static const char *luaMath[] = { - "abs", "acos", "asin", "atan", "atan2", "ceil", "cos", "cosh", "deg", - "exp", "floor", "fmod", "frexp", "ldexp", "log", "log10", "max", "min", - "modf", "pi", "pow", "rad", "random", "randomseed", "sin", "sinh", - "sqrt", "tan", "tanh", - NULL -}; - -static const char *luaTable[] = { - "concat", "insert", "maxn", "remove", "sort", - NULL -}; - -static const char *luaString[] = { - "byte", "char", "dump", "find", "format", "gmatch", "gsub", "len", - "lower", "match", "rep", "reverse", "sub", "upper", NULL -}; - -static const char *luaBbs[] = { - "ANSI_COLOR", "ANSI_RESET", "ESC", "addstr", "clear", "clock", - "clrtobot", "clrtoeol", "color", "ctime", "getch","getdata", - "getmaxyx", "getstr", "getyx", "interface", "kball", "kbhit", "kbreset", - "move", "moverel", "now", "outs", "pause", "print", "rect", "refresh", - "setattr", "sitename", "sleep", "strip_ansi", "time", "title", - "userid", "usernick", - NULL -}; - -static const char *luaToc[] = { - "author", "date", "interface", "latestref", - "notes", "title", "version", - NULL -}; - -static const char *luaBit[] = { - "arshift", "band", "bnot", "bor", "bxor", "cast", "lshift", "rshift", - NULL -}; - -static const char *luaStore[] = { - "USER", "GLOBAL", "iolimit", "limit", "load", "save", - NULL -}; - -static const char *luaLibs[] = { - "bbs", "bit", "math", "store", "string", "table", "toc", - NULL -}; -static const char**luaLibAPI[] = { - luaBbs, luaBit, luaMath, luaStore, luaString, luaTable, luaToc, - NULL -}; - -int synLuaKeyword(const char *text, int n, char *wlen) -{ - int i = 0; - const char **tbl = NULL; - if (*text >= 'A' && *text <= 'Z') - { - // normal identifier - while (n-- > 0 && (isalnum(*text) || *text == '_')) - { - text++; - (*wlen) ++; - } - return 0; - } - if (*text >= '0' && *text <= '9') - { - // digits - while (n-- > 0 && (isdigit(*text) || *text == '.' || *text == 'x')) - { - text++; - (*wlen) ++; - } - return 5; - } - if (*text == '#') - { - text++; - (*wlen) ++; - // length of identifier - while (n-- > 0 && (isalnum(*text) || *text == '_')) - { - text++; - (*wlen) ++; - } - return -2; - } - - // ignore non-identifiers - if (!(*text >= 'a' && *text <= 'z')) - return 0; - - // 1st, try keywords - for (i = 0; luaKeywords[i] && *text >= *luaKeywords[i]; i++) - { - int l = strlen(luaKeywords[i]); - if (n < l) - continue; - if (isalnum(text[l])) - continue; - if (strncmp(text, luaKeywords[i], l) == 0) - { - *wlen = l; - return 3; - } - } - for (i = 0; luaDataKeywords[i] && *text >= *luaDataKeywords[i]; i++) - { - int l = strlen(luaDataKeywords[i]); - if (n < l) - continue; - if (isalnum(text[l])) - continue; - if (strncmp(text, luaDataKeywords[i], l) == 0) - { - *wlen = l; - return 2; - } - } - for (i = 0; luaFunctions[i] && *text >= *luaFunctions[i]; i++) - { - int l = strlen(luaFunctions[i]); - if (n < l) - continue; - if (isalnum(text[l])) - continue; - if (strncmp(text, luaFunctions[i], l) == 0) - { - *wlen = l; - return 6; - } - } - for (i = 0; luaLibs[i]; i++) - { - int l = strlen(luaLibs[i]); - if (n < l) - continue; - if (text[l] != '.' && text[l] != ':') - continue; - if (strncmp(text, luaLibs[i], l) == 0) - { - *wlen = l+1; - text += l; text ++; - n -= l; n--; - break; - } - } - - tbl = luaLibAPI[i]; - if (!tbl) - { - // calcualte wlen - while (n-- > 0 && (isalnum(*text) || *text == '_')) - { - text++; - (*wlen) ++; - } - return 0; - } - - for (i = 0; tbl[i]; i++) - { - int l = strlen(tbl[i]); - if (n < l) - continue; - if (isalnum(text[l])) - continue; - if (strncmp(text, tbl[i], l) == 0) - { - *wlen += l; - return 6; - } - } - // luaLib. only - return -6; -} - -/** - * Just like outs, but print out '*' instead of 27(decimal) in the given string. - * - * FIXME column could not start from 0 - */ - -static void -edit_outs_attr_n(const char *text, int n, int attr) -{ - int column = 0; - register unsigned char inAnsi = 0; - register unsigned char ch; - int doReset = 0; - const char *reset = ANSI_RESET; - - // syntax attributes - char fComment = 0, - fSingleQuote = 0, - fDoubleQuote = 0, - fSquareQuote = 0, - fWord = 0; - -#ifdef COLORED_SELECTION - if ((attr & EOATTR_SELECTED) && - (attr & ~EOATTR_SELECTED)) - { - reset = ANSI_COLOR(0;7;36); - doReset = 1; - outs(reset); - } - else -#endif // if not defined, color by priority - selection first - if (attr & EOATTR_SELECTED) - { - reset = ANSI_COLOR(0;7); - doReset = 1; - outs(reset); - } - else if (attr & EOATTR_MOVIECODE) - { - reset = ANSI_COLOR(0;36); - doReset = 1; - outs(reset); - } - else if (attr & EOATTR_BBSLUA) - { - reset = ANSI_COLOR(0;1;31); - doReset = 1; - outs(reset); - } - else if (attr & EOATTR_COMMENT) - { - reset = ANSI_COLOR(0;1;34); - doReset = 1; - outs(reset); - } - -#ifdef DBCSAWARE - /* 0 = N/A, 1 = leading byte printed, 2 = ansi in middle */ - register unsigned char isDBCS = 0; -#endif - - while ((ch = *text++) && (++column < t_columns) && n-- > 0) - { - if(inAnsi == 1) - { - if(ch == ESC_CHR) - outc('*'); - else - { - outc(ch); - - if(!ANSI_IN_ESCAPE(ch)) - { - inAnsi = 0; - outs(reset); - } - } - - } - else if(ch == ESC_CHR) - { - inAnsi = 1; -#ifdef DBCSAWARE - if(isDBCS == 1) - { - isDBCS = 2; - outs(ANSI_COLOR(1;33) "?"); - outs(reset); - } -#endif - outs(ANSI_COLOR(1) "*"); - } - else - { -#ifdef DBCSAWARE - if(isDBCS == 1) - isDBCS = 0; - else if (isDBCS == 2) - { - /* ansi in middle. */ - outs(ANSI_COLOR(0;33) "?"); - outs(reset); - isDBCS = 0; - continue; - } - else - if(IS_BIG5_HI(ch)) - { - isDBCS = 1; - // peak next char - if(n > 0 && *text == ESC_CHR) - continue; - } -#endif - // Lua Parser! - if (!attr && curr_buf->synparser && !fComment) - { - // syntax highlight! - if (fSquareQuote) { - if (ch == ']' && n > 0 && *(text) == ']') - { - fSquareQuote = 0; - doReset = 0; - // directly print quotes - outc(ch); outc(ch); - text++, n--; - outs(ANSI_RESET); - continue; - } - } else if (fSingleQuote) { - if (ch == '\'') - { - fSingleQuote = 0; - doReset = 0; - // directly print quotes - outc(ch); - outs(ANSI_RESET); - continue; - } - } else if (fDoubleQuote) { - if (ch == '"') - { - fDoubleQuote = 0; - doReset = 0; - // directly print quotes - outc(ch); - outs(ANSI_RESET); - continue; - } - } else if (ch == '-' && n > 0 && *(text) == '-') { - fComment = 1; - doReset = 1; - outs(ANSI_COLOR(0;1;34)); - } else if (ch == '[' && n > 0 && *(text) == '[') { - fSquareQuote = 1; - doReset = 1; - fWord = 0; - outs(ANSI_COLOR(1;35)); - } else if (ch == '\'' || ch == '"') { - if (ch == '"') - fDoubleQuote = 1; - else - fSingleQuote = 1; - doReset = 1; - fWord = 0; - outs(ANSI_COLOR(1;35)); - } else { - // normal words - if (fWord) - { - // inside a word. - if (--fWord <= 0){ - fWord = 0; - doReset = 0; - outc(ch); - outs(ANSI_RESET); - continue; - } - } else if (isalnum(tolower(ch)) || ch == '#') { - char attr[] = ANSI_COLOR(0;1;37); - int x = synLuaKeyword(text-1, n+1, &fWord); - if (fWord > 0) - fWord --; - if (x != 0) - { - // sorry, fixed string here. - // 7 = *[0;1;3? - if (x<0) { attr[4] = '0'; x= -x; } - attr[7] = '0' + x; - prints(attr); - doReset = 1; - } - if (!fWord) - { - outc(ch); - outs(ANSI_RESET); - doReset = 0; - continue; - } - } - } - } - outc(ch); - } - } - - // this must be ANSI_RESET, not "reset". - if(inAnsi || doReset) - outs(ANSI_RESET); -} - -static void -edit_outs_attr(const char *text, int attr) -{ - edit_outs_attr_n(text, scr_cols, attr); -} - -static void -edit_ansi_outs_n(const char *str, int n, int attr) -{ - char c; - while (n-- > 0 && (c = *str++)) { - if(c == ESC_CHR && *str == '*') - { - // ptt prints - /* Because moving within ptt_prints is too hard - * let's just display it as-is. - */ - outc('*'); - } else { - outc(c); - } - } -} - -static void -edit_ansi_outs(const char *str, int attr) -{ - return edit_ansi_outs_n(str, strlen(str), attr); -} - -// old compatible API -void -edit_outs(const char *text) -{ - edit_outs_attr(text, 0); -} - -void -edit_outs_n(const char *text, int n) -{ - edit_outs_attr_n(text, n, 0); -} - - -#define PMORE_USE_ASCII_MOVIE // disable this if you don't enable ascii movie - -#ifdef PMORE_USE_ASCII_MOVIE -// pmore movie header support -unsigned char * - mf_movieFrameHeader(unsigned char *p, unsigned char *end); - -#endif // PMORE_USE_ASCII_MOVIE - -static int -detect_attr(const char *ps, size_t len) -{ - int attr = 0; - -#ifdef PMORE_USE_ASCII_MOVIE - if (mf_movieFrameHeader((unsigned char*)ps, (unsigned char*)ps+len)) - attr |= EOATTR_MOVIECODE; -#endif -#ifdef USE_BBSLUA - if (bbslua_isHeader(ps, ps + len)) - { - attr |= EOATTR_BBSLUA; - if (!curr_buf->synparser) - { - curr_buf->synparser = 1; - // if you need indent, toggle by hotkey. - // enabling indent by default may cause trouble to copy pasters - // curr_buf->indent_mode = 1; - } - } -#endif - return attr; -} - -static inline void -display_textline_internal(textline_t *p, int i) -{ - short tmp; - void (*output)(const char *, int) = edit_outs_attr; - void (*output_n)(const char *, int, int)= edit_outs_attr_n; - - int attr = EOATTR_NORMAL; - - move(i, 0); - clrtoeol(); - - if (!p) { - outc('~'); - outs(ANSI_CLRTOEND); - return; - } - - if (curr_buf->ansimode) { - output = edit_ansi_outs; - output_n = edit_ansi_outs_n; - } - - tmp = curr_buf->currln - curr_buf->curr_window_line + i; - - // parse attribute of line - - // selected attribute? - if (has_block_selection() && - ( (curr_buf->blockln <= curr_buf->currln && - curr_buf->blockln <= tmp && tmp <= curr_buf->currln) || - (curr_buf->currln <= tmp && tmp <= curr_buf->blockln)) ) - { - // outs(ANSI_COLOR(7)); // remove me when EOATTR is ready... - attr |= EOATTR_SELECTED; - } - - attr |= detect_attr(p->data, p->len); - -#ifdef DBCSAWARE - if(mbcs_mode && curr_buf->edit_margin > 0) - { - if(curr_buf->edit_margin >= p->len) - { - (*output)("", attr); - } else { - - int newpnt = curr_buf->edit_margin; - unsigned char *pdata = (unsigned char*) - (&p->data[0] + curr_buf->edit_margin); - - if(mbcs_mode) - newpnt = fix_cursor(p->data, newpnt, FC_LEFT); - - if(newpnt == curr_buf->edit_margin-1) - { - /* this should be always 'outs'? */ - // (*output)(ANSI_COLOR(1) "<" ANSI_RESET); - outs(ANSI_COLOR(1) "<" ANSI_RESET); - pdata++; - } - (*output)((char*)pdata, attr); - } - - } else -#endif - (*output)((curr_buf->edit_margin < p->len) ? - &p->data[curr_buf->edit_margin] : "", attr); - - if (attr) - outs(ANSI_RESET); - - // workaround poor terminal - outs(ANSI_CLRTOEND); -} - -static void -refresh_window(void) -{ - register textline_t *p; - register int i; - - for (p = curr_buf->top_of_win, i = 0; i < b_lines; i++) { - display_textline_internal(p, i); - - if (p) - p = p->next; - } - edit_msg(); -} - -static void -goto_line(int lino) -{ - if (lino > 0 && lino <= curr_buf->totaln + 1) { - textline_t *p; - - p = curr_buf->firstline; - curr_buf->currln = lino - 1; - - while (--lino && p->next) - p = p->next; - - if (p) - curr_buf->currline = p; - else { - curr_buf->currln = curr_buf->totaln; - curr_buf->currline = curr_buf->lastline; - } - - curr_buf->currpnt = 0; - - /* move window */ - if (curr_buf->currln < middle_line()) { - curr_buf->top_of_win = curr_buf->firstline; - curr_buf->curr_window_line = curr_buf->currln; - } else { - int i; - curr_buf->curr_window_line = middle_line(); - for (i = curr_buf->curr_window_line; i; i--) - p = p->prev; - curr_buf->top_of_win = p; - } - } - curr_buf->redraw_everything = YEA; -} - -static void -prompt_goto_line(void) -{ - char buf[10]; - - if (getdata(b_lines - 1, 0, "¸õ¦Ü²Ä´X¦æ:", buf, sizeof(buf), DOECHO)) - goto_line(atoi(buf)); -} - -/** - * search string interactively. - * @param mode 0: prompt - * 1: forward - * -1: backward - */ -static void -search_str(int mode) -{ - const int max_keyword = 65; - char *str; - char ans[4] = "n"; - - if (curr_buf->searched_string == NULL) { - if (mode != 0) - return; - curr_buf->searched_string = (char *)malloc(max_keyword * sizeof(char)); - curr_buf->searched_string[0] = 0; - } - - str = curr_buf->searched_string; - - if (!mode) { - if (getdata_buf(b_lines - 1, 0, "[·j´M]ÃöÁä¦r:", - str, max_keyword, DOECHO)) - if (*str) { - if (getdata(b_lines - 1, 0, "°Ï¤À¤j¤p¼g(Y/N/Q)? [N] ", - ans, sizeof(ans), LCECHO) && *ans == 'y') - curr_buf->substr_fp = strstr; - else - curr_buf->substr_fp = strcasestr; - } - } - if (*str && *ans != 'q') { - textline_t *p; - char *pos = NULL; - int lino; - - if (mode >= 0) { - for (lino = curr_buf->currln, p = curr_buf->currline; p; p = p->next, lino++) - if ((pos = (*curr_buf->substr_fp)(p->data + (lino == curr_buf->currln ? curr_buf->currpnt + 1 : 0), - str)) && (lino != curr_buf->currln || - pos - p->data != curr_buf->currpnt)) - break; - } else { - for (lino = curr_buf->currln, p = curr_buf->currline; p; p = p->prev, lino--) - if ((pos = (*curr_buf->substr_fp)(p->data, str)) && - (lino != curr_buf->currln || pos - p->data != curr_buf->currpnt)) - break; - } - if (pos) { - /* move window */ - curr_buf->currline = p; - curr_buf->currln = lino; - curr_buf->currpnt = pos - p->data; - if (lino < middle_line()) { - curr_buf->top_of_win = curr_buf->firstline; - curr_buf->curr_window_line = curr_buf->currln; - } else { - int i; - - curr_buf->curr_window_line = middle_line(); - for (i = curr_buf->curr_window_line; i; i--) - p = p->prev; - curr_buf->top_of_win = p; - } - curr_buf->redraw_everything = YEA; - } - } - if (!mode) - curr_buf->redraw_everything = YEA; -} - -/** - * move the cursor from bracket to corresponding bracket. - */ -static void -match_paren(void) -{ - char *parens = "()[]{}"; - int type; - int parenum = 0; - char *ptype; - textline_t *p; - int lino; - int c, i = 0; - - if (!(ptype = strchr(parens, curr_buf->currline->data[curr_buf->currpnt]))) - return; - - type = (ptype - parens) / 2; - parenum = ((ptype - parens) % 2) ? -1 : 1; - - /* FIXME CRASH */ - /* FIXME refactoring */ - if (parenum > 0) { - for (lino = curr_buf->currln, p = curr_buf->currline; p; p = p->next, lino++) { - int len = strlen(p->data); - for (i = (lino == curr_buf->currln) ? curr_buf->currpnt + 1 : 0; i < len; i++) { - if (p->data[i] == '/' && p->data[++i] == '*') { - ++i; - while (1) { - while (i < len && - !(p->data[i] == '*' && p->data[i + 1] == '/')) { - i++; - } - if (i >= len && p->next) { - p = p->next; - len = strlen(p->data); - ++lino; - i = 0; - } else - break; - } - } else if ((c = p->data[i]) == '\'' || c == '"') { - while (1) { - while (i < len - 1) { - if (p->data[++i] == '\\' && (size_t)i < len - 2) - ++i; - else if (p->data[i] == c) - goto end_quote; - } - if ((size_t)i >= len - 1 && p->next) { - p = p->next; - len = strlen(p->data); - ++lino; - i = -1; - } else - break; - } - end_quote: - ; - } else if ((ptype = strchr(parens, p->data[i])) && - (ptype - parens) / 2 == type) { - if (!(parenum += ((ptype - parens) % 2) ? -1 : 1)) - goto p_outscan; - } - } - } - } else { - for (lino = curr_buf->currln, p = curr_buf->currline; p; p = p->prev, lino--) { - int len = strlen(p->data); - for (i = ((lino == curr_buf->currln) ? curr_buf->currpnt - 1 : len - 1); i >= 0; i--) { - if (p->data[i] == '/' && p->data[--i] == '*' && i > 0) { - --i; - while (1) { - while (i > 0 && - !(p->data[i] == '*' && p->data[i - 1] == '/')) { - i--; - } - if (i <= 0 && p->prev) { - p = p->prev; - len = strlen(p->data); - --lino; - i = len - 1; - } else - break; - } - } else if ((c = p->data[i]) == '\'' || c == '"') { - while (1) { - while (i > 0) - if (i > 1 && p->data[i - 2] == '\\') - i -= 2; - else if ((p->data[--i]) == c) - goto begin_quote; - if (i <= 0 && p->prev) { - p = p->prev; - len = strlen(p->data); - --lino; - i = len; - } else - break; - } -begin_quote: - ; - } else if ((ptype = strchr(parens, p->data[i])) && - (ptype - parens) / 2 == type) { - if (!(parenum += ((ptype - parens) % 2) ? -1 : 1)) - goto p_outscan; - } - } - } - } -p_outscan: - if (!parenum) { - int top = curr_buf->currln - curr_buf->curr_window_line; - int bottom = curr_buf->currln - curr_buf->curr_window_line + b_lines - 1; - - curr_buf->currpnt = i; - curr_buf->currline = p; - curr_buf->curr_window_line += lino - curr_buf->currln; - curr_buf->currln = lino; - - if (lino < top || lino > bottom) { - if (lino < middle_line()) { - curr_buf->top_of_win = curr_buf->firstline; - curr_buf->curr_window_line = curr_buf->currln; - } else { - int i; - - curr_buf->curr_window_line = middle_line(); - for (i = curr_buf->curr_window_line; i; i--) - p = p->prev; - curr_buf->top_of_win = p; - } - curr_buf->redraw_everything = YEA; - } - } -} - -static void -currline_shift_left(void) -{ - int currpnt0; - - if (curr_buf->currline->len <= 0) - return; - - currpnt0 = curr_buf->currpnt; - curr_buf->currpnt = 0; - delete_char(); - curr_buf->currpnt = (currpnt0 <= curr_buf->currline->len) ? currpnt0 : currpnt0 - 1; - if (curr_buf->ansimode) - curr_buf->currpnt = ansi2n(n2ansi(curr_buf->currpnt, curr_buf->currline), curr_buf->currline); -} - -static void -currline_shift_right(void) -{ - int currpnt0; - - if (curr_buf->currline->len >= WRAPMARGIN - 1) - return; - - currpnt0 = curr_buf->currpnt; - curr_buf->currpnt = 0; - insert_char(' '); - curr_buf->currpnt = currpnt0; -} - -static void -cursor_to_next_word(void) -{ - while (curr_buf->currpnt < curr_buf->currline->len && - isalnum((int)curr_buf->currline->data[++curr_buf->currpnt])); - while (curr_buf->currpnt < curr_buf->currline->len && - isspace((int)curr_buf->currline->data[++curr_buf->currpnt])); -} - -static void -cursor_to_prev_word(void) -{ - while (curr_buf->currpnt && isspace((int)curr_buf->currline->data[--curr_buf->currpnt])); - while (curr_buf->currpnt && isalnum((int)curr_buf->currline->data[--curr_buf->currpnt])); - if (curr_buf->currpnt > 0) - curr_buf->currpnt++; -} - -static void -delete_current_word(void) -{ - while (curr_buf->currpnt < curr_buf->currline->len) { - delete_char(); - if (!isalnum((int)curr_buf->currline->data[curr_buf->currpnt])) - break; - } - while (curr_buf->currpnt < curr_buf->currline->len) { - delete_char(); - if (!isspace((int)curr_buf->currline->data[curr_buf->currpnt])) - break; - } -} - -/** - * transform every "*[" in given string to KEY_ESC "[" - */ -static void -transform_to_color(char *line) -{ - while (line[0] && line[1]) - if (line[0] == '*' && line[1] == '[') { - line[0] = KEY_ESC; - line += 2; - } else - ++line; -} - -static void -block_color(void) -{ - textline_t *begin, *end, *p; - - setup_block_begin_end(&begin, &end); - - p = begin; - while (1) { - // FIXME CRASH p will be NULL here. - assert(p); - transform_to_color(p->data); - if (p == end) - break; - else - p = p->next; - } - block_cancel(); -} - -/** - * insert ansi code - */ -static void -insert_ansi_code(void) -{ - int ch = curr_buf->insert_mode; - curr_buf->insert_mode = curr_buf->redraw_everything = YEA; - if (!curr_buf->ansimode) - insert_string(reset_color); - else { - char ans[4]; - move(b_lines - 2, 55); - outs(ANSI_COLOR(1;33;40) "B" ANSI_COLOR(41) "R" ANSI_COLOR(42) "G" ANSI_COLOR(43) "Y" ANSI_COLOR(44) "L" - ANSI_COLOR(45) "P" ANSI_COLOR(46) "C" ANSI_COLOR(47) "W" ANSI_RESET); - if (getdata(b_lines - 1, 0, - "½Ð¿é¤J «G«×/«e´º/I´º[¥¿±`¥Õ¦r¶Â©³][0wb]¡G", - ans, sizeof(ans), LCECHO)) - { - const char t[] = "BRGYLPCW"; - char color[15]; - char *tmp, *apos = ans; - int fg, bg; - - strcpy(color, ESC_STR "["); - if (isdigit((int)*apos)) { - sprintf(color,"%s%c", color, *(apos++)); - if (*apos) - strcat(color, ";"); - } - if (*apos) { - if ((tmp = strchr(t, toupper(*(apos++))))) - fg = tmp - t + 30; - else - fg = 37; - sprintf(color, "%s%d", color, fg); - } - if (*apos) { - if ((tmp = strchr(t, toupper(*(apos++))))) - bg = tmp - t + 40; - else - bg = 40; - sprintf(color, "%s;%d", color, bg); - } - strcat(color, "m"); - insert_string(color); - } else - insert_string(reset_color); - } - curr_buf->insert_mode = ch; -} - -static inline void -phone_mode_switch(void) -{ - if (curr_buf->phone_mode) - curr_buf->phone_mode = 0; - else { - curr_buf->phone_mode = 1; - if (!curr_buf->last_phone_mode) - curr_buf->last_phone_mode = 2; - } -} - -/** - * return coresponding phone char of given key c - */ -static const char* -phone_char(char c) -{ - if (curr_buf->last_phone_mode > 0 && curr_buf->last_phone_mode < 20) { - if (tolower(c)<'a'||(tolower(c)-'a') >= strlen(BIG5[curr_buf->last_phone_mode - 1]) / 2) - return 0; - return BIG5[curr_buf->last_phone_mode - 1] + (tolower(c) - 'a') * 2; - } - else if (curr_buf->last_phone_mode >= 20) { - if (c == '.') c = '/'; - - if (c < '/' || c > '9') - return 0; - - return table[curr_buf->last_phone_mode - 20] + (c - '/') * 2; - } - return 0; -} - -/** - * When get the key for phone mode, handle it (e.g. edit_msg) and return the - * key. Otherwise return 0. - */ -static inline char -phone_mode_filter(char ch) -{ - if (!curr_buf->phone_mode) - return 0; - - switch (ch) { - case 'z': - case 'Z': - if (curr_buf->last_phone_mode < 20) - curr_buf->last_phone_mode = 20; - else - curr_buf->last_phone_mode = 2; - edit_msg(); - return ch; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (curr_buf->last_phone_mode < 20) { - curr_buf->last_phone_mode = ch - '0' + 1; - curr_buf->redraw_everything = YEA; - return ch; - } - break; - case '-': - if (curr_buf->last_phone_mode < 20) { - curr_buf->last_phone_mode = 11; - curr_buf->redraw_everything = YEA; - return ch; - } - break; - case '=': - if (curr_buf->last_phone_mode < 20) { - curr_buf->last_phone_mode = 12; - curr_buf->redraw_everything = YEA; - return ch; - } - break; - case '`': - if (curr_buf->last_phone_mode < 20) { - curr_buf->last_phone_mode = 13; - curr_buf->redraw_everything = YEA; - return ch; - } - break; - case '/': - if (curr_buf->last_phone_mode >= 20) { - curr_buf->last_phone_mode += 4; - if (curr_buf->last_phone_mode > 27) - curr_buf->last_phone_mode -= 8; - curr_buf->redraw_everything = YEA; - return ch; - } - break; - case '*': - if (curr_buf->last_phone_mode >= 20) { - curr_buf->last_phone_mode++; - if ((curr_buf->last_phone_mode - 21) % 4 == 3) - curr_buf->last_phone_mode -= 4; - curr_buf->redraw_everything = YEA; - return ch; - } - break; - } - - return 0; -} - -#ifdef EXP_EDIT_UPLOAD - -static void -upload_file(void) -{ - size_t szdata = 0; - int c = 1; - char promptmsg = 0; - - clear(); - block_cancel(); - stand_title("¤W¶Ç¤å¦rÀÉ®×"); - move(3,0); - outs("§Q¥Î¥»ªA°È±z¥i¥H¤W¶Ç¸û¤jªº¤å¦rÀÉ (¦ý¤£p¤J½Z¶O)¡C\n" - "\n" - "¤W¶Ç´Á¶¡±z¥´ªº¦r¼È®É¤£·|¥X²{¦b¿Ã¹õ¤W¡A°£¤F Ctrl-U ·|³QÂà´«¬° ANSI \n" - "±±¨î½Xªº ESC ¥~¡A¨ä¥¦¯S®íÁä¤@«ß¨S¦³§@¥Î¡C\n" - "\n" - "½Ð¦b±zªº¹q¸£¥»¾÷ºÝ½Æ»s¦n¤º®e«á¶K¤W§Y¥i¶}©l¶Ç°e¡C\n"); - - do { - if (!num_in_buf()) - { - move(10, 0); clrtobot(); - prints("\n\n¸ê®Æ±µ¦¬¤¤... %u ¦ì¤¸²Õ¡C\n", (unsigned int)szdata); - outs(ANSI_COLOR(1) - "¡»¥þ³¡§¹¦¨«á«ö¤U End ©Î ^X/^Q/^C §Y¥i¦^¨ì½s¿èµe±¡C" - ANSI_RESET "\n"); - promptmsg = 0; - } - - c = igetch(); - if (c < 0x100 && isprint2(c)) - { - insert_char(c); - szdata ++; - } - else if (c == Ctrl('U') || c == ESC_CHR) - { - insert_char(ESC_CHR); - szdata ++; - } - else if (c == Ctrl('I')) - { - insert_tab(); - szdata ++; - } - else if (c == '\r' || c == '\n') - { - split(curr_buf->currline, curr_buf->currpnt); - curr_buf->oldcurrline = curr_buf->currline; - szdata ++; - promptmsg = 1; - } - - if (!promptmsg) - promptmsg = (szdata && szdata % 1024 == 0); - - // all other keys are ignored. - } while (c != KEY_END && c != Ctrl('X') && - c != Ctrl('C') && c != Ctrl('Q') && - curr_buf->totaln <= EDIT_LINE_LIMIT && - szdata <= EDIT_SIZE_LIMIT); - - move(12, 0); - prints("¶Ç°eµ²§ô: ¦¬¨ì %u ¦ì¤¸²Õ¡C", (unsigned int)szdata); - vmsgf("¦^¨ì½s¿èµe±"); -} - -#endif // EXP_EDIT_UPLOAD - - -/* ½s¿è³B²z¡G¥Dµ{¦¡¡BÁä½L³B²z */ -int -vedit2(char *fpath, int saveheader, int *islocal, int flags) -{ - char last = 0; /* the last key you press */ - int ch, tmp; - - int mode0 = currutmp->mode; - int destuid0 = currutmp->destuid; - int money = 0; - int interval = 0; - time4_t th = now; - int count = 0, tin = 0, quoted = 0; - char trans_buffer[256]; - char mytitle[STRLEN]; - - STATINC(STAT_VEDIT); - currutmp->mode = EDITING; - currutmp->destuid = currstat; - - strlcpy(mytitle, save_title, sizeof(mytitle)); - -#ifdef DBCSAWARE - mbcs_mode = (cuser.uflag & DBCSAWARE_FLAG) ? 1 : 0; -#endif - - enter_edit_buffer(); - - curr_buf->oldcurrline = curr_buf->currline = curr_buf->top_of_win = - curr_buf->firstline = curr_buf->lastline = alloc_line(WRAPMARGIN); - - if (*fpath) { - read_file(fpath, (flags & EDITFLAG_TEXTONLY) ? 1 : 0); - } - - if (*quote_file) { - do_quote(); - *quote_file = '\0'; - quoted = 1; - } - - if( curr_buf->oldcurrline != curr_buf->firstline || - curr_buf->currline != curr_buf->firstline) { - /* we must adjust because cursor (currentline) moved. */ - curr_buf->oldcurrline = curr_buf->currline = curr_buf->top_of_win = - curr_buf->firstline= adjustline(curr_buf->firstline, WRAPMARGIN); - } - - /* No matter you quote or not, just start the cursor from (0,0) */ - curr_buf->currpnt = curr_buf->currln = curr_buf->curr_window_line = - curr_buf->edit_margin = curr_buf->last_margin = 0; - - /* if quote, move to end of file. */ - if(quoted) - { - /* maybe do this in future. */ - } - - while (1) { - if (curr_buf->redraw_everything || has_block_selection()) { - refresh_window(); - curr_buf->redraw_everything = NA; - } - if( curr_buf->oldcurrline != curr_buf->currline ){ - curr_buf->oldcurrline = adjustline(curr_buf->oldcurrline, curr_buf->oldcurrline->len); - curr_buf->oldcurrline = curr_buf->currline = adjustline(curr_buf->currline, WRAPMARGIN); - } - - if (curr_buf->ansimode) - ch = n2ansi(curr_buf->currpnt, curr_buf->currline); - else - ch = curr_buf->currpnt - curr_buf->edit_margin; - move(curr_buf->curr_window_line, ch); - -#if 0 // DEPRECATED, it's really not a well known expensive feature - if (!curr_buf->line_dirty && strcmp(editline, curr_buf->currline->data)) - strcpy(editline, curr_buf->currline->data); -#endif - - ch = igetch(); - /* jochang debug */ - if ((interval = (now - th))) { - th = now; - if ((char)ch != last) { - money++; - last = (char)ch; - } - } - if (interval && interval == tin) - { // Ptt : +- 1 ¬í¤]ºâ - count++; - if(count>60) - { - money = 0; - count = 0; -/* - log_file("etc/illegal_money", LOG_CREAT | LOG_VF, - ANSI_COLOR(1;33;46) "%s " ANSI_COLOR(37;45) " ¥Î¾÷¾¹¤Hµoªí¤å³¹ " ANSI_COLOR(37) " %s" ANSI_RESET "\n", - cuser.userid, ctime4(&now)); - post_violatelaw(cuser.userid, BBSMNAME "¨t²Îĵ¹î", - "¥Î¾÷¾¹¤Hµoªí¤å³¹", "±j¨îÂ÷¯¸"); - abort_bbs(0); -*/ - } - } - else if(interval){ - count = 0; - tin = interval; - } -#ifndef DBCSAWARE - /* this is almost useless! */ - if (curr_buf->raw_mode) { - switch (ch) { - case Ctrl('S'): - case Ctrl('Q'): - case Ctrl('T'): - continue; - } - } -#endif - - if (phone_mode_filter(ch)) - continue; - - if (ch < 0x100 && isprint2(ch)) { - const char *pstr; - if(curr_buf->phone_mode && (pstr=phone_char(ch))) - insert_dchar(pstr); - else - insert_char(ch); - curr_buf->lastindent = -1; - } else { - if (ch == KEY_UP || ch == KEY_DOWN ){ - if (curr_buf->lastindent == -1) - curr_buf->lastindent = curr_buf->currpnt; - } else - curr_buf->lastindent = -1; - if (ch == KEY_ESC) - switch (KEY_ESC_arg) { - case ',': - ch = Ctrl(']'); - break; - case '.': - ch = Ctrl('T'); - break; - case 'v': - ch = KEY_PGUP; - break; - case 'a': - case 'A': - ch = Ctrl('V'); - break; - case 'X': - ch = Ctrl('X'); - break; - case 'q': - ch = Ctrl('Q'); - break; - case 'o': - ch = Ctrl('O'); - break; -#if 0 // DEPRECATED, it's really not a well known expensive feature - case '-': - ch = Ctrl('_'); - break; -#endif - case 's': - ch = Ctrl('S'); - break; - } - - switch (ch) { - case KEY_F10: - case Ctrl('X'): /* Save and exit */ - tmp = write_file(fpath, saveheader, islocal, mytitle, - (flags & EDITFLAG_UPLOAD) ? 1 : 0, - (flags & EDITFLAG_ALLOWTITLE) ? 1 : 0); - if (tmp != KEEP_EDITING) { - strlcpy(save_title, mytitle, sizeof(save_title)); - save_title[STRLEN-1] = 0; - currutmp->mode = mode0; - currutmp->destuid = destuid0; - - exit_edit_buffer(); - if (!tmp) - return money; - else - return tmp; - } - curr_buf->oldcurrline = curr_buf->currline; - curr_buf->redraw_everything = YEA; - break; - case KEY_F5: - prompt_goto_line(); - curr_buf->redraw_everything = YEA; - break; - case KEY_F8: - t_users(); - curr_buf->redraw_everything = YEA; - break; - case Ctrl('W'): - block_cut(); - // curr_buf->oldcurrline is freed in block_cut, and currline is - // well adjusted now. This will avoid re-adjusting later. - // It's not a good implementation, try to find a better - // solution! - curr_buf->oldcurrline = curr_buf->currline; - break; - case Ctrl('Q'): /* Quit without saving */ - grayout(0, b_lines-1, GRAYOUT_DARK); - ch = vmsg("µ²§ô¦ý¤£Àx¦s [y/N]? "); - if (ch == 'y' || ch == 'Y') { - currutmp->mode = mode0; - currutmp->destuid = destuid0; - exit_edit_buffer(); - return -1; - } - curr_buf->redraw_everything = YEA; - break; - case Ctrl('C'): - insert_ansi_code(); - break; - case KEY_ESC: - switch (KEY_ESC_arg) { - case 'U': - t_users(); - curr_buf->redraw_everything = YEA; - break; - case 'i': - t_idle(); - curr_buf->redraw_everything = YEA; - break; - case 'n': - search_str(1); - break; - case 'p': - search_str(-1); - break; - case 'L': - case 'J': - prompt_goto_line(); - curr_buf->redraw_everything = YEA; - break; - case ']': - match_paren(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - read_tmpbuf(KEY_ESC_arg - '0'); - curr_buf->oldcurrline = curr_buf->currline; - curr_buf->redraw_everything = YEA; - break; - case 'l': /* block delete */ - case ' ': - if (has_block_selection()) { - block_prompt(); - // curr_buf->oldcurrline is freed in block_cut, and currline is - // well adjusted now. This will avoid re-adjusting later. - // It's not a good implementation, try to find a better - // solution! - curr_buf->oldcurrline = curr_buf->currline; - } - else - block_select(); - break; - case 'u': - block_cancel(); - break; - case 'c': - block_copy(); - break; - case 'y': - curr_buf->oldcurrline = undelete_line(); - if (curr_buf->oldcurrline == NULL) - curr_buf->oldcurrline = curr_buf->currline; - break; - case 'R': -#ifdef DBCSAWARE - case 'r': - mbcs_mode =! mbcs_mode; -#endif - curr_buf->raw_mode ^= 1; - break; - case 'I': - curr_buf->indent_mode ^= 1; - break; - case 'j': - currline_shift_left(); - break; - case 'k': - currline_shift_right(); - break; - case 'f': - cursor_to_next_word(); - break; - case 'b': - cursor_to_prev_word(); - break; - case 'd': - delete_current_word(); - break; - } - break; - case Ctrl('S'): - case KEY_F3: - search_str(0); - break; - case Ctrl('U'): - insert_char(ESC_CHR); - break; - case Ctrl('V'): /* Toggle ANSI color */ - curr_buf->ansimode ^= 1; - if (curr_buf->ansimode && has_block_selection()) - block_color(); - clear(); - curr_buf->redraw_everything = YEA; - break; - case Ctrl('I'): - insert_tab(); - break; - case '\r': - case '\n': - block_cancel(); - if (curr_buf->totaln >= EDIT_LINE_LIMIT) - { - vmsg("Àɮפw¶W¹L³Ì¤j¨î¡AµLªk¦A¼W¥[¦æ¼Æ¡C"); - break; - } - -#ifdef MAX_EDIT_LINE - if(curr_buf->totaln == - ((flags & EDITFLAG_ALLOWLARGE) ? - MAX_EDIT_LINE_LARGE : MAX_EDIT_LINE)) - { - vmsg("¤w¨ì¹F³Ì¤j¦æ¼Æ¨î¡C"); - break; - } -#endif - split(curr_buf->currline, curr_buf->currpnt); - curr_buf->oldcurrline = curr_buf->currline; - break; - case Ctrl('G'): - { - unsigned int currstat0 = currstat; - setutmpmode(EDITEXP); - a_menu("½s¿è»²§U¾¹", "etc/editexp", - (HasUserPerm(PERM_SYSOP) ? SYSOP : NOBODY), - 0, - trans_buffer); - currstat = currstat0; - } - if (trans_buffer[0]) { - FILE *fp1; - if ((fp1 = fopen(trans_buffer, "r"))) { - int indent_mode0 = curr_buf->indent_mode; - char buf[WRAPMARGIN + 2]; - - curr_buf->indent_mode = 0; - while (fgets(buf, sizeof(buf), fp1)) { - if (!strncmp(buf, "§@ªÌ:", 5) || - !strncmp(buf, "¼ÐÃD:", 5) || - !strncmp(buf, "®É¶¡:", 5)) - continue; - insert_string(buf); - } - fclose(fp1); - curr_buf->indent_mode = indent_mode0; - while (curr_buf->curr_window_line >= b_lines) { - curr_buf->curr_window_line--; - curr_buf->top_of_win = curr_buf->top_of_win->next; - } - } - } - curr_buf->redraw_everything = YEA; - break; - case Ctrl('P'): - phone_mode_switch(); - curr_buf->redraw_everything = YEA; - break; - - case KEY_F1: - case Ctrl('Z'): /* Help */ - more("etc/ve.hlp", YEA); - curr_buf->redraw_everything = YEA; - break; - case Ctrl('L'): - clear(); - curr_buf->redraw_everything = YEA; - break; - case KEY_LEFT: - if (curr_buf->currpnt) { - if (curr_buf->ansimode) - curr_buf->currpnt = n2ansi(curr_buf->currpnt, curr_buf->currline); - curr_buf->currpnt--; - if (curr_buf->ansimode) - curr_buf->currpnt = ansi2n(curr_buf->currpnt, curr_buf->currline); -#ifdef DBCSAWARE - if(mbcs_mode) - curr_buf->currpnt = fix_cursor(curr_buf->currline->data, curr_buf->currpnt, FC_LEFT); -#endif - } else if (curr_buf->currline->prev) { - curr_buf->curr_window_line--; - curr_buf->currln--; - curr_buf->currline = curr_buf->currline->prev; - curr_buf->currpnt = curr_buf->currline->len; - } - break; - case KEY_RIGHT: - if (curr_buf->currline->len != curr_buf->currpnt) { - if (curr_buf->ansimode) - curr_buf->currpnt = n2ansi(curr_buf->currpnt, curr_buf->currline); - curr_buf->currpnt++; - if (curr_buf->ansimode) - curr_buf->currpnt = ansi2n(curr_buf->currpnt, curr_buf->currline); -#ifdef DBCSAWARE - if(mbcs_mode) - curr_buf->currpnt = fix_cursor(curr_buf->currline->data, curr_buf->currpnt, FC_RIGHT); -#endif - } else if (curr_buf->currline->next) { - curr_buf->currpnt = 0; - curr_buf->curr_window_line++; - curr_buf->currln++; - curr_buf->currline = curr_buf->currline->next; - } - break; - case KEY_UP: - cursor_to_prev_line(); - break; - case KEY_DOWN: - cursor_to_next_line(); - break; - - case Ctrl('B'): - case KEY_PGUP: { - short tmp = curr_buf->currln; - curr_buf->top_of_win = back_line(curr_buf->top_of_win, t_lines - 2); - curr_buf->currln = tmp; - curr_buf->currline = back_line(curr_buf->currline, t_lines - 2); - curr_buf->curr_window_line = get_lineno_in_window(); - if (curr_buf->currpnt > curr_buf->currline->len) - curr_buf->currpnt = curr_buf->currline->len; - curr_buf->redraw_everything = YEA; - break; - } - - case Ctrl('F'): - case KEY_PGDN: { - short tmp = curr_buf->currln; - curr_buf->top_of_win = forward_line(curr_buf->top_of_win, t_lines - 2); - curr_buf->currln = tmp; - curr_buf->currline = forward_line(curr_buf->currline, t_lines - 2); - curr_buf->curr_window_line = get_lineno_in_window(); - if (curr_buf->currpnt > curr_buf->currline->len) - curr_buf->currpnt = curr_buf->currline->len; - curr_buf->redraw_everything = YEA; - break; - } - - case KEY_END: - case Ctrl('E'): - curr_buf->currpnt = curr_buf->currline->len; - break; - case Ctrl(']'): /* start of file */ - curr_buf->currline = curr_buf->top_of_win = curr_buf->firstline; - curr_buf->currpnt = curr_buf->currln = curr_buf->curr_window_line = 0; - curr_buf->redraw_everything = YEA; - break; - case Ctrl('T'): /* tail of file */ - curr_buf->top_of_win = back_line(curr_buf->lastline, t_lines - 1); - curr_buf->currline = curr_buf->lastline; - curr_buf->curr_window_line = get_lineno_in_window(); - curr_buf->currln = curr_buf->totaln; - curr_buf->redraw_everything = YEA; - curr_buf->currpnt = 0; - break; - case KEY_HOME: - case Ctrl('A'): - curr_buf->currpnt = 0; - break; - case Ctrl('O'): // better not use ^O - UNIX not sending. - case KEY_INS: /* Toggle insert/overwrite */ - if (has_block_selection() && curr_buf->insert_mode) { - char ans[4]; - - getdata(b_lines - 1, 0, - "°Ï¶ô·L½Õ¥k²¾´¡¤J¦r¤¸(¹w³]¬°ªÅ¥Õ¦r¤¸)", - ans, sizeof(ans), LCECHO); - curr_buf->insert_c = ans[0] ? ans[0] : ' '; - } - curr_buf->insert_mode ^= 1; - break; - case Ctrl('H'): - case '\177': /* backspace */ - block_cancel(); - if (curr_buf->ansimode) { - curr_buf->ansimode = 0; - clear(); - curr_buf->redraw_everything = YEA; - } else { - if (curr_buf->currpnt == 0) { - if (!curr_buf->currline->prev) - break; - curr_buf->curr_window_line--; - curr_buf->currln--; - - curr_buf->currline = adjustline(curr_buf->currline, curr_buf->currline->len); - curr_buf->currline = curr_buf->currline->prev; - curr_buf->currline = adjustline(curr_buf->currline, WRAPMARGIN); - curr_buf->oldcurrline = curr_buf->currline; - - curr_buf->currpnt = curr_buf->currline->len; - curr_buf->redraw_everything = YEA; - if (curr_buf->currline->next == curr_buf->top_of_win) { - curr_buf->top_of_win = curr_buf->currline; - curr_buf->curr_window_line = 0; - } - if (*next_non_space_char(curr_buf->currline->next->data) == '\0') { - delete_line(curr_buf->currline->next, 0); - break; - } - join(curr_buf->currline); - break; - } -#ifndef DBCSAWARE - curr_buf->currpnt--; - delete_char(); -#else - { - int newpnt = curr_buf->currpnt - 1; - - if(mbcs_mode) - newpnt = fix_cursor(curr_buf->currline->data, newpnt, FC_LEFT); - - for(; curr_buf->currpnt > newpnt;) - { - curr_buf->currpnt --; - delete_char(); - } - } -#endif - } - break; - case Ctrl('D'): - case KEY_DEL: /* delete current character */ - block_cancel(); - if (curr_buf->currline->len == curr_buf->currpnt) { - join(curr_buf->currline); - curr_buf->redraw_everything = YEA; - } else { -#ifndef DBCSAWARE - delete_char(); -#else - { - int w = 1; - - if(mbcs_mode) - w = mchar_len((unsigned char*)(curr_buf->currline->data + curr_buf->currpnt)); - - for(; w > 0; w --) - delete_char(); - } -#endif - if (curr_buf->ansimode) - curr_buf->currpnt = ansi2n(n2ansi(curr_buf->currpnt, curr_buf->currline), curr_buf->currline); - } - break; - case Ctrl('Y'): /* delete current line */ - curr_buf->currline->len = curr_buf->currpnt = 0; - case Ctrl('K'): /* delete to end of line */ - block_cancel(); - if (curr_buf->currline->len == 0) { - textline_t *p = curr_buf->currline->next; - if (!p) { - p = curr_buf->currline->prev; - if (!p) { - curr_buf->currline->data[0] = 0; - break; - } - if (curr_buf->curr_window_line > 0) { - curr_buf->curr_window_line--; - } - curr_buf->currln--; - } - if (curr_buf->currline == curr_buf->top_of_win) - curr_buf->top_of_win = p; - - delete_line(curr_buf->currline, 1); - curr_buf->currline = p; - curr_buf->redraw_everything = YEA; - curr_buf->oldcurrline = curr_buf->currline = adjustline(curr_buf->currline, WRAPMARGIN); - break; - } - else if (curr_buf->currline->len == curr_buf->currpnt) { - join(curr_buf->currline); - curr_buf->redraw_everything = YEA; - break; - } - curr_buf->currline->len = curr_buf->currpnt; - curr_buf->currline->data[curr_buf->currpnt] = '\0'; - break; - } - - if (curr_buf->currln < 0) - curr_buf->currln = 0; - - if (curr_buf->curr_window_line < 0) - window_scroll_down(); - else if (cursor_at_bottom_line()) - window_scroll_up(); -#ifdef DBCSAWARE - if(mbcs_mode) - curr_buf->currpnt = fix_cursor(curr_buf->currline->data, curr_buf->currpnt, FC_LEFT); -#endif - } - - if (curr_buf->ansimode) - tmp = n2ansi(curr_buf->currpnt, curr_buf->currline); - else - tmp = curr_buf->currpnt; - - if (tmp < t_columns - 1) - curr_buf->edit_margin = 0; - else - curr_buf->edit_margin = tmp / (t_columns - 8) * (t_columns - 8); - - if (!curr_buf->redraw_everything) { - if (curr_buf->edit_margin != curr_buf->last_margin) { - curr_buf->last_margin = curr_buf->edit_margin; - curr_buf->redraw_everything = YEA; - } else { - move(curr_buf->curr_window_line, 0); - clrtoeol(); - if (curr_buf->ansimode) - outs(curr_buf->currline->data); - else - { - int attr = EOATTR_NORMAL; - attr |= detect_attr(curr_buf->currline->data, curr_buf->currline->len); - edit_outs_attr(&curr_buf->currline->data[curr_buf->edit_margin], attr); - } - outs(ANSI_RESET ANSI_CLRTOEND); - edit_msg(); - } - } /* redraw */ - } /* main event loop */ - - exit_edit_buffer(); -} - -int -vedit(char *fpath, int saveheader, int *islocal) -{ - return vedit2(fpath, saveheader, islocal, EDITFLAG_ALLOWTITLE); -} - -/* vim:sw=4:nofoldenable - */ diff --git a/mbbsd/emaildb.c b/mbbsd/emaildb.c deleted file mode 100644 index fa057102..00000000 --- a/mbbsd/emaildb.c +++ /dev/null @@ -1,244 +0,0 @@ -/* $Id$ */ -#include <sqlite3.h> -#include "bbs.h" - -#define EMAILDB_PATH BBSHOME "/emaildb.db" - -// define FORK model to minimize memory usage. -#define FORK_MODEL - -static int emaildb_open(sqlite3 **Db) { - int rc; - - if ((rc = sqlite3_open(EMAILDB_PATH, Db)) != SQLITE_OK) - return rc; - - // create table if it doesn't exist - rc = sqlite3_exec(*Db, "CREATE TABLE IF NOT EXISTS emaildb (userid TEXT, email TEXT, PRIMARY KEY (userid));" - "CREATE INDEX IF NOT EXISTS email ON emaildb (email);", - NULL, NULL, NULL); - - return rc; -} - -#ifndef INIT_MAIN -int emaildb_check_email(char * email, int email_len) -{ - int count = -1; - pid_t pid = -1; - sqlite3 *Db = NULL; - sqlite3_stmt *Stmt = NULL; - -#ifdef FORK_MODEL - switch((pid = fork())) - { - case -1: // error - break; - - case 0: // child - break; - - default: - waitpid(pid, &count, 0); - count = WEXITSTATUS(count); - // vmsgf(ANSI_RESET "found %d emails", count); - return count; - } -#endif - - if (emaildb_open(&Db) != SQLITE_OK) - goto end; - - if (sqlite3_prepare(Db, "SELECT userid FROM emaildb WHERE email LIKE lower(?);", - -1, &Stmt, NULL) != SQLITE_OK) - goto end; - - if (sqlite3_bind_text(Stmt, 1, email, email_len, SQLITE_STATIC) != SQLITE_OK) - goto end; - - count = 0; - while (sqlite3_step(Stmt) == SQLITE_ROW) { - char *result; - userec_t u; - - if ((result = (char*)sqlite3_column_text(Stmt, 0)) == NULL) - break; - - // ignore my self, because I may be the one going to - // use mail. - if (strcasecmp(result, cuser.userid) == 0) - continue; - - // force update - u.email[0] = 0; - - if (getuser(result, &u)) - if (strcasecmp(email, u.email) == 0) - count++; - } - -end: - if (Stmt != NULL) - if (sqlite3_finalize(Stmt) != SQLITE_OK) - count = -1; - - if (Db != NULL) - sqlite3_close(Db); - - if (pid == 0) - exit(count); - - return count; -} -#endif - -int emaildb_update_email(char * userid, int userid_len, char * email, int email_len) -{ - int ret = -1; - pid_t pid = -1; - -#ifdef FORK_MODEL - switch((pid = fork())) - { - case -1: // error - break; - - case 0: // child - break; - - default: - waitpid(pid, &ret, 0); - ret = WEXITSTATUS(ret); - return ret; - } -#endif - - sqlite3 *Db = NULL; - sqlite3_stmt *Stmt = NULL; - - if (emaildb_open(&Db) != SQLITE_OK) - goto end; - - if (sqlite3_prepare(Db, "REPLACE INTO emaildb (userid, email) VALUES (lower(?),lower(?));", - -1, &Stmt, NULL) != SQLITE_OK) - goto end; - - if (sqlite3_bind_text(Stmt, 1, userid, userid_len, SQLITE_STATIC) != SQLITE_OK) - goto end; - - if (sqlite3_bind_text(Stmt, 2, email, email_len, SQLITE_STATIC) != SQLITE_OK) - goto end; - - if (sqlite3_step(Stmt) == SQLITE_DONE) - ret = 0; - -end: - if (Stmt != NULL) - sqlite3_finalize(Stmt); - if (Db != NULL) - sqlite3_close(Db); - - if (pid == 0) - exit(ret); - - return ret; -} - -#ifdef INIT_MAIN - -// standalone initialize builder - -#define TRANSCATION_PERIOD (4096) -int main() -{ - int fd = 0; - userec_t xuser; - off_t sz = 0, i = 0, valids = 0; - sqlite3 *Db = NULL; - sqlite3_stmt *Stmt = NULL, *tranStart = NULL, *tranEnd = NULL; - - // init passwd - sz = dashs(FN_PASSWD); - fd = open(FN_PASSWD, O_RDONLY); - if (fd < 0 || sz <= 0) - { - fprintf(stderr, "cannot open ~/.PASSWDS.\n"); - return 0; - } - sz /= sizeof(userec_t); - - // init emaildb - if (emaildb_open(&Db) != SQLITE_OK) - { - fprintf(stderr, "cannot initialize emaildb.\n"); - return 0; - } - - if (sqlite3_prepare(Db, "REPLACE INTO emaildb (userid, email) VALUES (lower(?),lower(?));", - -1, &Stmt, NULL) != SQLITE_OK || - sqlite3_prepare(Db, "BEGIN TRANSACTION;", -1, &tranStart, NULL) != SQLITE_OK || - sqlite3_prepare(Db, "COMMIT;", -1, &tranEnd, NULL) != SQLITE_OK) - { - fprintf(stderr, "SQLite 3 internal error.\n"); - return 0; - } - - sqlite3_step(tranStart); - sqlite3_reset(tranStart); - while (read(fd, &xuser, sizeof(xuser)) == sizeof(xuser)) - { - i++; - // got a record - if (strlen(xuser.userid) < 2 || strlen(xuser.userid) > IDLEN) - continue; - if (strlen(xuser.email) < 5) - continue; - - if (sqlite3_bind_text(Stmt, 1, xuser.userid, strlen(xuser.userid), - SQLITE_STATIC) != SQLITE_OK) - { - fprintf(stderr, "\ncannot prepare userid param.\n"); - break; - } - if (sqlite3_bind_text(Stmt, 2, xuser.email, strlen(xuser.email), - SQLITE_STATIC) != SQLITE_OK) - { - fprintf(stderr, "\ncannot prepare email param.\n"); - break; - } - - if (sqlite3_step(Stmt) != SQLITE_DONE) - { - fprintf(stderr, "\ncannot execute statement.\n"); - break; - } - sqlite3_reset(Stmt); - - valids ++; - if (valids % 10 == 0) - fprintf(stderr, "%d/%d (valid: %d)\r", - (int)i, (int)sz, (int)valids); - if (valids % TRANSCATION_PERIOD == 0) - { - sqlite3_step(tranEnd); - sqlite3_step(tranStart); - sqlite3_reset(tranEnd); - sqlite3_reset(tranStart); - } - } - - if (valids % TRANSCATION_PERIOD) - sqlite3_step(tranEnd); - - if (Stmt != NULL) - sqlite3_finalize(Stmt); - - if (Db != NULL) - sqlite3_close(Db); - - close(fd); - return 0; -} -#endif - -// vim: sw=4 diff --git a/mbbsd/fav.c b/mbbsd/fav.c deleted file mode 100644 index 8a6c1e2f..00000000 --- a/mbbsd/fav.c +++ /dev/null @@ -1,1320 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -/** - * Structure - * ========= - * fav Àɪº«e¨âÓ byte ¬Oª©¸¹¡A±µ¤U¨Ó¤~¬O¯u¥¿ªº data¡C - * - * fav ªº¥Dn¬[ºc¦p¤U¡G - * - * fav_t - ¥Î¨Ó¸Ë¦UºØ entry(fav_type_t) ªº directory - * ¶i¤J§Úªº³Ì·R®É¡A¬Ý¨ìªºªF¦è´N¬O®Ú¾Ú fav_t ¥Í¥X¨Óªº¡C - * ¸Ì±¬ö¿ýªÌ¡A³o¤@Ó level ¤¤¦³¦h¤ÖӬݪO¡B¥Ø¿ý¡B¤À¹j½u¡C(favh) - * ¬O¤@Ó array (with pre-allocated buffer) - * - * fav_type_t - fav entry ªº base class - * ¦s¨ú®É³z¹L type Åܼƨӱoª¾¥¿½Tªº«¬ºA¡C - * - * fav_board_t / fav_line_t / fav_folder_t - derived class - * ¸Ô²Ó±¡§Î½Ð°Ñ¦Ò fav.h ¤¤ªº©w¸q¡C - * ¥H cast_(board|line|folder)_t ¨Ó±N¤@Ó fav_type_t §@°ÊºAÂ૬¡C - * - * Policy - * ====== - * ¬°¤FÁקK¹L«×ªº¸ê®Æ·h²¾¡A·í±N¤@Ó item ±q§Úªº³Ì·R¤¤²¾°£®É¡A¥u±N¥Lªº - * FAVH_FAV flag ²¾°£¡C¦Ó¨S¦³³oÓ flag ªº item ¤]¤£³Qµø¬°§Úªº³Ì·R¡C - * - * §Úªº³Ì·R¤¤¡A¨S³] FAVH_FAV ªº¸ê®Æ¡A±N¦b¬Y¨Ç®ÉÔ¡A¦p¼g¤JÀɮ׮ɡA©I¥s - * rebuild_fav ²M°£°®²b¡C - * - * Others - * ====== - * ¯¸ªø·h²¾¬ÝªO©Ò¥Îªº t ¡A¦]¬°¤£¯à¥u¦s¦b nbrd ¸Ì±¡A¤S¤£µM¦A§Ë¥XÃB¥~ªºªÅ¶¡¡A - * ©Ò¥H·í¯¸ªø¤£¦b§Úªº³Ì·R«ö¤F t ¡A·|§â³oÓ°O¿ý¼È¦s¦b fav ¤¤ - * (FAVH_ADM_TAG == 1, FAVH_FAV == 0)¡C - */ - - -/* the total number of items, every level. */ -static int fav_number; - -/* definition of fav stack, the top one is in use now. */ -static int fav_stack_num = 0; -static fav_t *fav_stack[FAV_MAXDEPTH] = {0}; - -static char dirty = 0; - -/* fav_tmp is for recordinge while copying, moving, etc. */ -static fav_t *fav_tmp; -//static int fav_tmp_snum; /* the sequence number in favh in fav_t */ - -#if 1 // DEPRECATED -static void fav4_read_favrec(FILE *frp, fav_t *fp); -#endif - -static void fav_free_branch(fav_t *fp); - -/** - * cast_(board|line|folder) ¤@±Ú¥Î©ó±N base class §@Â૬ - * (¤£Àˬd¹ê»Ú data type) - */ -inline static fav_board_t *cast_board(fav_type_t *p){ - return (fav_board_t *)p->fp; -} - -inline static fav_line_t *cast_line(fav_type_t *p){ - return (fav_line_t *)p->fp; -} - -inline static fav_folder_t *cast_folder(fav_type_t *p){ - return (fav_folder_t *)p->fp; -} - -/** - * ¶Ç¦^«ü©wªº fp(dir) ¤¤ªº fp->DataTail, ²Ä¤@Ó¨S¥Î¹Lªº¦ì¸mªº index - */ -inline static int get_data_tail(fav_t *fp){ - return fp->DataTail; -} - -/** - * ¶Ç¦^«ü©w dir ¤¤©Ò¥Îªº entry ªºÁ`¼Æ (¥uºâ¯uªº¦b¸Ì±¡A¦Ó¤£ºâ¤w³Q²¾°£ªº) - */ -inline int get_data_number(fav_t *fp){ - return fp->nBoards + fp->nLines + fp->nFolders; -} - -/** - * ¶Ç¦^¥Ø«e©Ò¦bªº dir pointer - */ -inline fav_t *get_current_fav(void){ - if (fav_stack_num == 0) - return NULL; - return fav_stack[fav_stack_num - 1]; -} - -/** - * ±N ft(entry) cast ¦¨¤@Ó dir - */ -inline fav_t *get_fav_folder(fav_type_t *ft){ - return cast_folder(ft)->this_folder; -} - -inline int get_item_type(fav_type_t *ft){ - return ft->type; -} - -/** - * ±N¤@Ó«ü©wªº dir pointer ¦s¤U¨Ó¡A¤§«á¥i¥Î fav_get_tmp_fav ¨Ó¦s¥Î - */ -inline static void fav_set_tmp_folder(fav_t *fp){ - fav_tmp = fp; -} - -inline static fav_t *fav_get_tmp_fav(void){ - return fav_tmp; -} - -/** - * ±N fp(dir) °Oªº¼Æ¶q¤¤¡A¦©°£¤@³æ¦ì ft(entry) - */ -static void fav_decrease(fav_t *fp, fav_type_t *ft) -{ - dirty = 1; - - switch (get_item_type(ft)){ - case FAVT_BOARD: - fp->nBoards--; - break; - case FAVT_LINE: - fp->nLines--; - break; - case FAVT_FOLDER: - fp->nFolders--; - break; - } - fav_number--; -} - -/** - * ±N fp(dir) °Oªº¼Æ¶q¤¤¡A¼W¥[¤@³æ¦ì ft(entry) - */ -static void fav_increase(fav_t *fp, fav_type_t *ft) -{ - dirty = 1; - - switch (get_item_type(ft)){ - case FAVT_BOARD: - fp->nBoards++; - break; - case FAVT_LINE: - fp->nLines++; - cast_line(ft)->lid = ++fp->lineID; - break; - case FAVT_FOLDER: - fp->nFolders++; - cast_folder(ft)->fid = ++fp->folderID; - break; - } - fav_number++; - fp->DataTail++; -} - -inline static int get_folder_num(fav_t *fp) { - return fp->nFolders; -} - -/** - * get_(folder|line)_id ¶Ç¦^ fp ¤¤¤@Ó·sªº folder/line id - */ -inline static int get_folder_id(fav_t *fp) { - return fp->folderID; -} - -inline static int get_line_id(fav_t *fp) { - return fp->lineID; -} - -inline static int get_line_num(fav_t *fp) { - return fp->nLines; -} - -/** - * ³]©w¬YÓ flag¡C - * @bit: ¥Ø«e©Ò¦³ flags ¦³: FAVH_FAV, FAVH_TAG, FAVH_UNREAD, FAVH_ADM_TAG - * @param cmd: FALSE: unset, TRUE: set, EXCH: opposite - */ -void set_attr(fav_type_t *ft, int bit, char cmd){ - if (ft == NULL) - return; - if (cmd == EXCH) - ft->attr ^= bit; - else if (cmd == TRUE) - ft->attr |= bit; - else - ft->attr &= ~bit; - dirty = 1; -} - -inline int is_set_attr(fav_type_t *ft, char bit){ - return ft->attr & bit; -} - -char *get_item_title(fav_type_t *ft) -{ - switch (get_item_type(ft)){ - case FAVT_BOARD: - assert(0<=cast_board(ft)->bid-1 && cast_board(ft)->bid-1<MAX_BOARD); - return bcache[cast_board(ft)->bid - 1].brdname; - case FAVT_FOLDER: - return cast_folder(ft)->title; - case FAVT_LINE: - return "----"; - } - return NULL; -} - -static char *get_item_class(fav_type_t *ft) -{ - switch (get_item_type(ft)){ - case FAVT_BOARD: - assert(0<=cast_board(ft)->bid-1 && cast_board(ft)->bid-1<MAX_BOARD); - return bcache[cast_board(ft)->bid - 1].title; - case FAVT_FOLDER: - return "¥Ø¿ý"; - case FAVT_LINE: - return "----"; - } - return NULL; -} - - -static int get_type_size(int type) -{ - switch (type){ - case FAVT_BOARD: - return sizeof(fav_board_t); - case FAVT_FOLDER: - return sizeof(fav_folder_t); - case FAVT_LINE: - return sizeof(fav_line_t); - } - assert(0); - return 0; -} - -inline static void* fav_malloc(int size){ - void *p; - assert(size>0); - p = (void *)malloc(size); - assert(p); - memset(p, 0, size); - return p; -} - -/** - * ¥u½Æ»s fav_type_t - */ -inline static void -fav_item_copy(fav_type_t *target, const fav_type_t *source){ - target->type = source->type; - target->attr = source->attr; - target->fp = source->fp; -} - -inline fav_t *get_fav_root(void){ - return fav_stack[0]; -} - -/** - * ¬O§_¬°¦³®Äªº entry - */ -inline int valid_item(fav_type_t *ft){ - return ft->attr & FAVH_FAV; -} - -static int is_need_rebuild_fav(fav_t *fp) -{ - int i, nData; - fav_type_t *ft; - - nData = fp->DataTail; - - for (i = 0; i < nData; i++){ - if (!valid_item(&fp->favh[i])) - return 1; - - ft = &fp->favh[i]; - switch (get_item_type(ft)){ - case FAVT_BOARD: - case FAVT_LINE: - break; - case FAVT_FOLDER: - if(is_need_rebuild_fav(get_fav_folder(&fp->favh[i]))) - return 1; - break; - default: - return 1; - } - } - return 0; -} -/** - * ²M°£ fp(dir) ¤¤µL®Äªº entry/dir¡C¡uµL®Ä¡v«üªº¬O¨S¦³ FAVH_FAV flag¡A©Ò¥H - * ¤£¥]§t¤£¦s¦bªº¬ÝªO¡C - */ -static void rebuild_fav(fav_t *fp) -{ - int i, j, nData; - fav_type_t *ft; - - fav_number -= get_data_number(fp); - fp->lineID = fp->folderID = 0; - fp->nLines = fp->nFolders = fp->nBoards = 0; - nData = fp->DataTail; - fp->DataTail = 0; - - for (i = 0, j = 0; i < nData; i++){ - if (!valid_item(&fp->favh[i])) - continue; - - ft = &fp->favh[i]; - switch (get_item_type(ft)){ - case FAVT_BOARD: - case FAVT_LINE: - break; - case FAVT_FOLDER: - rebuild_fav(get_fav_folder(&fp->favh[i])); - break; - default: - continue; - } - fav_increase(fp, &fp->favh[i]); - if (i != j) - fav_item_copy(&fp->favh[j], &fp->favh[i]); - j++; - } - fp->DataTail = get_data_number(fp); -} - -inline void fav_cleanup(void) -{ - if (is_need_rebuild_fav(get_fav_root())) - rebuild_fav(get_fav_root()); -} - -/* sort the fav */ -static int favcmp_by_name(const void *a, const void *b) -{ - return strcasecmp(get_item_title((fav_type_t *)a), get_item_title((fav_type_t *)b)); -} - -void fav_sort_by_name(void) -{ - fav_t *fp = get_current_fav(); - - if (fp == NULL) - return; - - dirty = 1; - rebuild_fav(fp); - qsort(fp->favh, get_data_number(fp), sizeof(fav_type_t), favcmp_by_name); -} - -static int favcmp_by_class(const void *a, const void *b) -{ - fav_type_t *f1, *f2; - int cmp; - - f1 = (fav_type_t *)a; - f2 = (fav_type_t *)b; - if (get_item_type(f1) == FAVT_FOLDER) - return -1; - if (get_item_type(f2) == FAVT_FOLDER) - return 1; - if (get_item_type(f1) == FAVT_LINE) - return 1; - if (get_item_type(f2) == FAVT_LINE) - return -1; - - cmp = strncasecmp(get_item_class(f1), get_item_class(f2), 4); - if (cmp) - return cmp; - return strcasecmp(get_item_title(f1), get_item_title(f2)); -} - -void fav_sort_by_class(void) -{ - fav_t *fp = get_current_fav(); - - if (fp == NULL) - return; - - dirty = 1; - rebuild_fav(fp); - qsort(fp->favh, get_data_number(fp), sizeof(fav_type_t), favcmp_by_class); -} - -/** - * The following is the movement operations in the user interface. - */ - -/** - * ¥Ø¿ý¼h¼Æ¬O§_¹F¨ì³Ì¤jÈ FAV_MAXDEPTH - */ -inline int fav_stack_full(void){ - return fav_stack_num >= FAV_MAXDEPTH; -} - -inline static int fav_stack_push_fav(fav_t *fp){ - if (fav_stack_full()) - return -1; - fav_stack[fav_stack_num++] = fp; - return 0; -} - -inline static int fav_stack_push(fav_type_t *ft){ -// if (ft->type != FAVT_FOLDER) -// return -1; - return fav_stack_push_fav(get_fav_folder(ft)); -} - -inline static void fav_stack_pop(void){ - fav_stack[--fav_stack_num] = NULL; -} - -void fav_folder_in(int fid) -{ - fav_type_t *tmp = getfolder(fid); - if (get_item_type(tmp) == FAVT_FOLDER){ - fav_stack_push(tmp); - } -} - -void fav_folder_out(void) -{ - fav_stack_pop(); -} - -static int is_valid_favtype(int type) -{ - switch (type){ - case FAVT_BOARD: - case FAVT_FOLDER: - case FAVT_LINE: - return 1; - } - return 0; -} - -/** - * @return 0 if success, -1 if failed - */ -static int read_favrec(FILE *frp, fav_t *fp) -{ - /* TODO handle read errors */ - int i; - fav_type_t *ft; - - fread(&fp->nBoards, sizeof(fp->nBoards), 1, frp); - fread(&fp->nLines, sizeof(fp->nLines), 1, frp); - fread(&fp->nFolders, sizeof(fp->nFolders), 1, frp); - fp->DataTail = get_data_number(fp); - fp->nAllocs = fp->DataTail + FAV_PRE_ALLOC; - fp->lineID = fp->folderID = 0; - fp->favh = (fav_type_t *)fav_malloc(sizeof(fav_type_t) * fp->nAllocs); - fav_number += get_data_number(fp); - - for(i = 0; i < fp->DataTail; i++){ - ft = &fp->favh[i]; - fread(&ft->type, sizeof(ft->type), 1, frp); - if(!is_valid_favtype(ft->type)) { - ft->type = 0; - return -1; - } - fread(&ft->attr, sizeof(ft->attr), 1, frp); - ft->fp = (void *)fav_malloc(get_type_size(ft->type)); - - switch (ft->type) { - case FAVT_FOLDER: - fread(&cast_folder(ft)->fid, sizeof(char), 1, frp); - fread(&cast_folder(ft)->title, BTLEN + 1, 1, frp); - break; - case FAVT_BOARD: - case FAVT_LINE: - fread(ft->fp, get_type_size(ft->type), 1, frp); - break; - } - } - - for(i = 0; i < fp->DataTail; i++){ - ft = &fp->favh[i]; - switch (ft->type) { - case FAVT_FOLDER: { - fav_t *p = (fav_t *)fav_malloc(sizeof(fav_t)); - if(read_favrec(frp, p)<0) { - fav_free_branch(p); - return -1; - } - cast_folder(ft)->this_folder = p; - cast_folder(ft)->fid = ++(fp->folderID); - break; - } - case FAVT_LINE: - cast_line(ft)->lid = ++(fp->lineID); - break; - } - } - return 0; -} - -/** - * ±q°O¿ýÀɤ¤ load ¥X§Úªº³Ì·R¡C - * TODO create default fav, and add SYSOP/PttNewHand (see reginit_fav) - */ -int fav_load(void) -{ - FILE *frp; - char buf[PATHLEN]; - unsigned short version; - fav_t *fp; - if (fav_stack_num > 0) - return -1; - setuserfile(buf, FAV); - - if (!dashf(buf)) { -#if 1 // DEPRECATED - char old[PATHLEN]; - setuserfile(old, FAV4); - if (dashf(old)) { - if ((frp = fopen(old, "r")) == NULL) - return -1; - fp = (fav_t *)fav_malloc(sizeof(fav_t)); - fav_number = 0; - fav4_read_favrec(frp, fp); - fav_stack_push_fav(fp); - fclose(frp); - - fav_save(); - setuserfile(old, FAV ".bak"); - Copy(buf, old); - } - else -#endif - { - fp = (fav_t *)fav_malloc(sizeof(fav_t)); - fav_number = 0; - fav_stack_push_fav(fp); - } - return 0; - } - - if ((frp = fopen(buf, "r")) == NULL) - return -1; -#ifdef CRITICAL_MEMORY - // kcwu: dirty hack, avoid 64byte slot. use 128 instead. - fp = (fav_t *)fav_malloc(sizeof(fav_t)+64); -#else - fp = (fav_t *)fav_malloc(sizeof(fav_t)); -#endif - fav_number = 0; - fread(&version, sizeof(version), 1, frp); - // if (version != FAV_VERSION) { ... } - if(read_favrec(frp, fp)<0) { - // load fail - fav_free_branch(fp); - fav_number = 0; - fp = (fav_t *)fav_malloc(sizeof(fav_t)); - } - fav_stack_push_fav(fp); - fclose(frp); - dirty = 0; - return 0; -} - -/* write to the rec file */ -static void write_favrec(FILE *fwp, fav_t *fp) -{ - int i; - fav_type_t *ft; - - if (fp == NULL) - return; - - fwrite(&fp->nBoards, sizeof(fp->nBoards), 1, fwp); - fwrite(&fp->nLines, sizeof(fp->nLines), 1, fwp); - fwrite(&fp->nFolders, sizeof(fp->nFolders), 1, fwp); - fp->DataTail = get_data_number(fp); - - for(i = 0; i < fp->DataTail; i++){ - ft = &fp->favh[i]; - fwrite(&ft->type, sizeof(ft->type), 1, fwp); - fwrite(&ft->attr, sizeof(ft->attr), 1, fwp); - - switch (ft->type) { - case FAVT_FOLDER: - fwrite(&cast_folder(ft)->fid, sizeof(char), 1, fwp); - fwrite(&cast_folder(ft)->title, BTLEN + 1, 1, fwp); - break; - case FAVT_BOARD: - case FAVT_LINE: - fwrite(ft->fp, get_type_size(ft->type), 1, fwp); - break; - } - } - - for(i = 0; i < fp->DataTail; i++){ - if (fp->favh[i].type == FAVT_FOLDER) - write_favrec(fwp, get_fav_folder(&fp->favh[i])); - } -} - -/** - * §â°O¿ýÀÉ save ¶i§Úªº³Ì·R¡C - * @note fav_cleanup() ·|¥ý³Q©I¥s¡C - */ -int fav_save(void) -{ - FILE *fwp; - char buf[PATHLEN], buf2[PATHLEN]; - unsigned short version = FAV_VERSION; - fav_t *fp = get_fav_root(); - if (fp == NULL) - return -1; - - fav_cleanup(); - if (!dirty) - return 0; - - setuserfile(buf2, FAV); - snprintf(buf, sizeof(buf), "%s.tmp.%x",buf2, getpid()); - fwp = fopen(buf, "w"); - if(fwp == NULL) - return -1; - fwrite(&version, sizeof(version), 1, fwp); - write_favrec(fwp, fp); - - if(fclose(fwp)==0) - Rename(buf, buf2); - - return 0; -} - -/** - * remove ft (³]¬° invalid¡A¹ê»Ú¤W·|µ¥¨ì save ®É¤~²M°£) - */ -static inline void fav_free_item(fav_type_t *ft) -{ - set_attr(ft, 0xFFFF, FALSE); -} - -/** - * delete ft from fp - */ -static int fav_remove(fav_t *fp, fav_type_t *ft) -{ - if (fp == NULL || ft == NULL) - return -1; - fav_free_item(ft); - fav_decrease(fp, ft); - return 0; -} - -/** - * free the mem of fp recursively - */ -static void fav_free_branch(fav_t *fp) -{ - int i; - fav_type_t *ft; - if (fp == NULL) - return; - for(i = 0; i < fp->DataTail; i++){ - ft = &fp->favh[i]; - switch(get_item_type(ft)){ - case FAVT_FOLDER: - fav_free_branch(cast_folder(ft)->this_folder); - break; - case FAVT_BOARD: - case FAVT_LINE: - if (ft->fp) - free(ft->fp); - break; - } - } - free(fp->favh); - free(fp); - fp = NULL; -} - -/** - * free the mem of the whole fav tree recursively - */ -void fav_free(void) -{ - fav_free_branch(get_fav_root()); - - /* reset the stack */ - fav_stack_num = 0; -} - -/** - * ±q¥Ø«eªº dir ¤¤§ä¥X¯S©wÃþ§O (type)¡Bid ¬° id ªº entry¡C - * §ä¤£¨ì¶Ç¦^ NULL - */ -static fav_type_t *get_fav_item(int id, int type) -{ - int i; - fav_type_t *ft; - fav_t *fp = get_current_fav(); - - if (fp == NULL) - return NULL; - - for(i = 0; i < fp->DataTail; i++){ - ft = &fp->favh[i]; - if (!valid_item(ft) || get_item_type(ft) != type) - continue; - if (fav_getid(ft) == id) - return ft; - } - return NULL; -} - -/** - * ±q¥Ø«eªº dir ¤¤ remove ¯S©wÃþ§O (type)¡Bid ¬° id ªº entry¡C - */ -void fav_remove_item(int id, char type) -{ - fav_remove(get_current_fav(), get_fav_item(id, type)); -} - -/** - * get*(bid) ¶Ç¦^¥Ø«eªº dir ¤¤¸ÓÃþ§O id == bid ªº entry¡C - */ -fav_type_t *getadmtag(int bid) -{ - int i; - fav_t *fp = get_fav_root(); - fav_type_t *ft; - assert(0<=bid-1 && bid-1<MAX_BOARD); - for (i = 0; i < fp->DataTail; i++) { - ft = &fp->favh[i]; - if (get_item_type(ft) == FAVT_BOARD && cast_board(ft)->bid == bid && is_set_attr(ft, FAVH_ADM_TAG)) - return ft; - } - return NULL; -} - -fav_type_t *getboard(int bid) -{ - assert(0<=bid-1 && bid-1<MAX_BOARD); - return get_fav_item(bid, FAVT_BOARD); -} - -fav_type_t *getfolder(int fid) -{ - return get_fav_item(fid, FAVT_FOLDER); -} - -char *get_folder_title(int fid) -{ - return get_item_title(get_fav_item(fid, FAVT_FOLDER)); -} - - -char getbrdattr(int bid) -{ - fav_type_t *fb = getboard(bid); - if (!fb) - return 0; - return fb->attr; -} - -int fav_getid(fav_type_t *ft) -{ - switch(get_item_type(ft)){ - case FAVT_FOLDER: - return cast_folder(ft)->fid; - case FAVT_LINE: - return cast_line(ft)->lid; - case FAVT_BOARD: - return cast_board(ft)->bid; - } - return -1; -} - -inline static int is_maxsize(void){ - return fav_number >= MAX_FAV; -} - -/** - * ¨C¦¸¤@Ó dir º¡®É¡A³oÓ function ·|±N buffer ¤j¤p½Õ¤j FAV_PRE_ALLOC Ó¡A - * ª½¨ì¤W¬°¤î¡C - */ -static int enlarge_if_full(fav_t *fp) -{ - fav_type_t * p; - /* enlarge the volume if need. */ - if (is_maxsize()) - return -1; - if (fp->DataTail < fp->nAllocs) - return 1; - - /* realloc and clean the tail */ - p = (fav_type_t *)realloc(fp->favh, sizeof(fav_type_t) * (fp->nAllocs + FAV_PRE_ALLOC)); - if( p == NULL ) - return -1; - - fp->favh = p; - memset(fp->favh + fp->nAllocs, 0, sizeof(fav_type_t) * FAV_PRE_ALLOC); - fp->nAllocs += FAV_PRE_ALLOC; - return 0; -} - -/** - * pre-append an item, and return the reference back. - */ -static fav_type_t *fav_preappend(fav_t *fp, int type) -{ - fav_type_t *item; - if (enlarge_if_full(fp) < 0) - return NULL; - item = &fp->favh[fp->DataTail]; - item->fp = fav_malloc(get_type_size(type)); - item->attr = FAVH_FAV; - item->type = type; - fav_increase(fp, item); - return item; -} - -static void move_in_folder(fav_t *fav, int src, int dst) -{ - int i, count; - fav_type_t tmp; - - if (fav == NULL) - return; - count = get_data_number(fav); - if (src >= fav->DataTail) - src = count; - if (dst >= fav->DataTail) - dst = count; - if (src == dst) - return; - - dirty = 1; - - /* Find real locations of src and dst in fav->favh[] */ - for(count = i = 0; count <= src && i < fav->DataTail; i++) - if (valid_item(&fav->favh[i])) - count++; - if (count != src + 1) return; - src = i - 1; - for(count = i = 0; count <= dst && i < fav->DataTail; i++) - if (valid_item(&fav->favh[i])) - count++; - if (count != dst + 1) return; - dst = i - 1; - - fav_item_copy(&tmp, &fav->favh[src]); - - if (src < dst) { - for(i = src; i < dst; i++) - fav_item_copy(&fav->favh[i], &fav->favh[i + 1]); - } - else { // dst < src - for(i = src; i > dst; i--) - fav_item_copy(&fav->favh[i], &fav->favh[i - 1]); - } - fav_item_copy(&fav->favh[dst], &tmp); -} - -/** - * ±N¥Ø«e¥Ø¿ý¤¤²Ä src Ó entry ²¾¨ì dst¡C - * @note src/dst ¬O user ¹ê»Ú¤W¬Ý¨ìªº¦ì¸m¡A¤]´N¬O¤£¥]§t invalid entry¡C - */ -void move_in_current_folder(int from, int to) -{ - move_in_folder(get_current_fav(), from, to); -} - -/** - * the following defines the interface of add new fav_XXX - */ - -/** - * allocate ¤@Ó folder entry - */ -inline static fav_t *alloc_folder_item(void){ - fav_t *fp = (fav_t *)fav_malloc(sizeof(fav_t)); - fp->nAllocs = FAV_PRE_ALLOC; - fp->favh = (fav_type_t *)fav_malloc(sizeof(fav_type_t) * FAV_PRE_ALLOC); - return fp; -} - -/** - * ·s¼W¤@¤À¹j½u - * @return ¥[¤Jªº entry «ü¼Ð - */ -fav_type_t *fav_add_line(void) -{ - fav_t *fp = get_current_fav(); - if (is_maxsize()) - return NULL; - if (fp == NULL || get_line_num(fp) >= MAX_LINE) - return NULL; - return fav_preappend(fp, FAVT_LINE); -} - -/** - * ·s¼W¤@¥Ø¿ý - * @return ¥[¤Jªº entry «ü¼Ð - */ -fav_type_t *fav_add_folder(void) -{ - fav_t *fp = get_current_fav(); - fav_type_t *ft; - if (is_maxsize() || fav_stack_full()) - return NULL; - if (fp == NULL || get_folder_num(fp) >= MAX_FOLDER) - return NULL; - ft = fav_preappend(fp, FAVT_FOLDER); - if (ft == NULL) - return NULL; - cast_folder(ft)->this_folder = alloc_folder_item(); - return ft; -} - -/** - * ±N«ü©w¬ÝªO¥[¤J¥Ø«eªº¥Ø¿ý¡C - * @return ¥[¤Jªº entry «ü¼Ð - * @note ¤£¤¹³\¦P¤@ÓªO³Q¥[¤J¨â¦¸ - */ -fav_type_t *fav_add_board(int bid) -{ - fav_t *fp = get_current_fav(); - fav_type_t *ft = getboard(bid); - - if (fp == NULL) - return NULL; - if (ft != NULL) - return ft; - - if (is_maxsize()) - return NULL; - ft = fav_preappend(fp, FAVT_BOARD); - if (ft == NULL) - return NULL; - cast_board(ft)->bid = bid; - return ft; -} - -/** - * for administrator to move/administrate board - */ -fav_type_t *fav_add_admtag(int bid) -{ - fav_t *fp = get_fav_root(); - fav_type_t *ft; - if (is_maxsize()) - return NULL; - ft = fav_preappend(fp, FAVT_BOARD); - set_attr(ft, FAVH_FAV, FALSE); - cast_board(ft)->bid = bid; - // turn on FAVH_ADM_TAG - set_attr(ft, FAVH_ADM_TAG, TRUE); - return ft; -} - - -/* everything about the tag in fav mode. - * I think we don't have to implement the function 'cross-folder' tag.*/ - -/** - * ±N¥Ø«e¥Ø¿ý¤U¡A¥Ñ type & id «ü©wªº entry ¼Ð¤W/¨ú®ø tag - * @param bool ¦P set_attr - * @note Y¦P¤@ӥؿý¤£©¯¦³¦P¼ËªºªF¦è¡A¥u¦³²Ä¤@Ó·|§@¥Î¡C - */ -void fav_tag(int id, char type, char bool) { - fav_type_t *ft = get_fav_item(id, type); - if (ft != NULL) - set_attr(ft, FAVH_TAG, bool); -} - -static void fav_dosomething_tagged_item(fav_t *fp, int (*act)(fav_t *, fav_type_t *)) -{ - int i; - for(i = 0; i < fp->DataTail; i++){ - if (valid_item(&fp->favh[i]) && is_set_attr(&fp->favh[i], FAVH_TAG)) - if ((*act)(fp, &fp->favh[i]) < 0) - break; - } -} - -static int remove_tagged_item(fav_t *fp, fav_type_t *ft) -{ - // do not remove the folder if it's on the stack - if (get_item_type(ft) == FAVT_FOLDER) { - int i; - for(i = 0; i < FAV_MAXDEPTH && fav_stack[i] != NULL; i++) { - if (fav_stack[i] == get_fav_folder(ft)){ - set_attr(ft, FAVH_TAG, FALSE); - return 0; - } - } - } - return fav_remove(fp, ft); -} - -inline static int fav_remove_tagged_item(fav_t *fp){ - fav_dosomething_tagged_item(fp, remove_tagged_item); - return 0; -} - -/* add an item into a fav_t. - * here we must give the line and foler a new id to prevent an old one is exist. - */ -static int add_and_remove_tag(fav_t *fp, fav_type_t *ft) -{ - fav_type_t *tmp; - // do not remove the folder if it's on the stack - if (get_item_type(ft) == FAVT_FOLDER) { - int i; - for(i = 0; i < FAV_MAXDEPTH && fav_stack[i] != NULL; i++) { - if (fav_stack[i] == get_fav_folder(ft)){ - set_attr(ft, FAVH_TAG, FALSE); - return 0; - } - } - } - tmp = fav_preappend(fav_get_tmp_fav(), ft->type); - if (ft->type == FAVT_FOLDER) { - strlcpy(cast_folder(tmp)->title, cast_folder(ft)->title, BTLEN + 1); - cast_folder(tmp)->this_folder = cast_folder(ft)->this_folder; - } - else { - memcpy(tmp->fp, ft->fp, get_type_size(ft->type)); - } - - - free(ft->fp); - ft->fp = NULL; - set_attr(tmp, FAVH_TAG, FALSE); - fav_remove(fp, ft); - return 0; -} - -inline static int fav_add_tagged_item(fav_t *fp){ - if (fp == fav_get_tmp_fav()) - return -1; - fav_dosomething_tagged_item(fp, add_and_remove_tag); - return 0; -} - -static void fav_do_recursively(fav_t *fp, int (*act)(fav_t *)) -{ - int i; - fav_type_t *ft; - for(i = 0; i < fp->DataTail; i++){ - ft = &fp->favh[i]; - if (!valid_item(ft)) - continue; - if (get_item_type(ft) == FAVT_FOLDER && get_fav_folder(ft) != NULL){ - fav_do_recursively(get_fav_folder(ft), act); - } - } - (*act)(fp); -} - -static void fav_dosomething_all_tagged_item(int (*act)(fav_t *)) -{ - fav_do_recursively(get_fav_root(), act); -} - -/** - * fav_*_all_tagged_item ¦b¾ãÓ§Úªº³Ì·R¤W¹ï¤w¼Ð¤W tag ªº entry °µ¬Y¥ó¨Æ¡C - */ -void fav_remove_all_tagged_item(void) -{ - fav_dosomething_all_tagged_item(fav_remove_tagged_item); -} - -void fav_add_all_tagged_item(void) -{ - fav_set_tmp_folder(get_current_fav()); - fav_dosomething_all_tagged_item(fav_add_tagged_item); -} - -inline static int remove_tag(fav_t *fp, fav_type_t *ft) -{ - set_attr(ft, FAVH_TAG, FALSE); - return 0; -} - -inline static int remove_tags(fav_t *fp) -{ - fav_dosomething_tagged_item(fp, remove_tag); - return 0; -} - -/** - * ²¾°£§Úªº³Ì·R©Ò¦³ªº tags - */ -void fav_remove_all_tag(void) -{ - fav_dosomething_all_tagged_item(remove_tags); -} - -/** - * ³]©w folder ªº¤¤¤å¦WºÙ - */ -void fav_set_folder_title(fav_type_t *ft, char *title) -{ - if (get_item_type(ft) != FAVT_FOLDER) - return; - dirty = 1; - strlcpy(cast_folder(ft)->title, title, sizeof(cast_folder(ft)->title)); -} - -#define BRD_OLD 0 -#define BRD_NEW 1 -#define BRD_END 2 -/** - * ¦pªG user ¶}±Ò FAVNEW_FLAG ªº¥\¯à: - * mode == 1: update ¬ÝªO¡A¨Ã±N·s¬ÝªO¥[¤J§Úªº³Ì·R¡C - * mode == 0: update ¸ê°T¦ý¤£¥[¤J¡C - * - * @return ¥[¤Jªº¬ÝªO¼Æ - * PS. count ´NÅý¥¦¼Æ§¹¡A¤~¤£·|¦b¤U¤@¦¸ login ¤S±q¤@¥b¶}©l¼Æ¡C - */ -int updatenewfav(int mode) -{ - /* mode: 0: don't write to fav 1: write to fav */ - int i, fd, brdnum; - int count = 0; - char fname[80], *brd; - - if(!(cuser.uflag2 & FAVNEW_FLAG)) - return 0; - - setuserfile(fname, FAVNB); - - if( (fd = open(fname, O_RDWR | O_CREAT, 0600)) != -1 ){ - - assert(numboards>=0); - brdnum = numboards; /* avoid race */ - - if ((brd = (char *)malloc((brdnum + 1) * sizeof(char))) == NULL) - return -1; - memset(brd, 0, (brdnum + 1) * sizeof(char)); - - i = read(fd, brd, brdnum * sizeof(char)); - if (i < 0) { - free(brd); - close(fd); - vmsg("favorite subscription error"); - return -1; - } - - brd[i] = BRD_END; - - for(i = 0; i < brdnum && brd[i] != BRD_END; i++){ - if(brd[i] == BRD_NEW){ - /* check the permission if the board exsits */ - if(bcache[i].brdname[0] && HasBoardPerm(&bcache[i])){ - if(mode && !(bcache[i].brdattr & BRD_SYMBOLIC)) { - fav_add_board(i + 1); - count++; - } - brd[i] = BRD_OLD; - } - } - else{ - if(!bcache[i].brdname[0]) - brd[i] = BRD_NEW; - } - } - - if( i < brdnum) { // the board number may change - for(; i < brdnum; ++i){ - if(bcache[i].brdname[0] && HasBoardPerm(&bcache[i])){ - if(mode && !(bcache[i].brdattr & BRD_SYMBOLIC)) { - fav_add_board(i + 1); - count++; - } - brd[i] = BRD_OLD; - } - else - brd[i] = BRD_NEW; - } - } - - brd[i] = BRD_END; - - lseek(fd, 0, SEEK_SET); - write(fd, brd, (brdnum + 1) * sizeof(char)); - - free(brd); - close(fd); - } - - return count; -} - -void subscribe_newfav(void) -{ - updatenewfav(0); -} - -// create defaults for new user -void reginit_fav(void) -{ - int bid = 0; - - fav_load(); // for creating root - -#ifdef GLOBAL_NEWBIE - bid = getbnum(GLOBAL_NEWBIE); - if (bid > 0) fav_add_board(bid); -#endif - -#ifdef GLOBAL_TEST - bid = getbnum(GLOBAL_TEST); - if (bid > 0) fav_add_board(bid); -#endif - -#ifdef GLOBAL_ASKBOARD - bid = getbnum(GLOBAL_ASKBOARD); - if (bid > 0) fav_add_board(bid); -#endif - -#ifdef GLOBAL_SYSOP - bid = getbnum(GLOBAL_SYSOP); - if (bid > 0) fav_add_board(bid); -#endif - - fav_save(); -} - -#if 1 // DEPRECATED -typedef struct { - char fid; - char title[BTLEN + 1]; - int this_folder; -} fav_folder4_t; - -typedef struct { - int bid; - time4_t lastvisit; /* UNUSED */ - char attr; -} fav4_board_t; - -static int fav4_get_type_size(int type) -{ - switch (type){ - case FAVT_BOARD: - return sizeof(fav4_board_t); - case FAVT_FOLDER: - return sizeof(fav_folder_t); - case FAVT_LINE: - return sizeof(fav_line_t); - } - return 0; -} - -static void fav4_read_favrec(FILE *frp, fav_t *fp) -{ - int i; - fav_type_t *ft; - - fread(&fp->nBoards, sizeof(fp->nBoards), 1, frp); - fread(&fp->nLines, sizeof(fp->nLines), 1, frp); - fread(&fp->nFolders, sizeof(fp->nFolders), 1, frp); - fp->DataTail = get_data_number(fp); - fp->nAllocs = fp->DataTail + FAV_PRE_ALLOC; - fp->lineID = fp->folderID = 0; - fp->favh = (fav_type_t *)fav_malloc(sizeof(fav_type_t) * fp->nAllocs); - fav_number += get_data_number(fp); - - for(i = 0; i < fp->DataTail; i++){ - ft = &fp->favh[i]; - fread(&ft->type, sizeof(ft->type), 1, frp); - fread(&ft->attr, sizeof(ft->attr), 1, frp); - ft->fp = (void *)fav_malloc(fav4_get_type_size(ft->type)); - - /* TODO A pointer has different size between 32 and 64-bit arch. - * But the pointer in fav_folder_t is irrelevant here. - * In order not to touch the current .fav4, fav_folder4_t is used - * here. It should be FIXED in the next version. */ - switch (ft->type) { - case FAVT_FOLDER: - fread(ft->fp, sizeof(fav_folder4_t), 1, frp); - break; - case FAVT_BOARD: - case FAVT_LINE: - fread(ft->fp, fav4_get_type_size(ft->type), 1, frp); - break; - } - } - - for(i = 0; i < fp->DataTail; i++){ - ft = &fp->favh[i]; - switch (ft->type) { - case FAVT_FOLDER: { - fav_t *p = (fav_t *)fav_malloc(sizeof(fav_t)); - fav4_read_favrec(frp, p); - cast_folder(ft)->this_folder = p; - cast_folder(ft)->fid = ++(fp->folderID); - break; - } - case FAVT_LINE: - cast_line(ft)->lid = ++(fp->lineID); - break; - } - } -} -#endif - -// vim:ts=8:sw=4 diff --git a/mbbsd/file.c b/mbbsd/file.c deleted file mode 100644 index 3b657acc..00000000 --- a/mbbsd/file.c +++ /dev/null @@ -1,186 +0,0 @@ -/* $Id$ */ - -#include "bbs.h" - -/** - * file.c ¬O°w¹ï¥H"¦æ"¬°³æ¦ìªºÀɮשҩw¸qªº¤@¨Ç operation¡C - */ - -/** - * ¶Ç¦^ file Àɪº¦æ¼Æ - * @param file - */ -int file_count_line(const char *file) -{ - FILE *fp; - int count = 0; - char buf[200]; - - if ((fp = fopen(file, "r"))) { - while (fgets(buf, sizeof(buf), fp)) { - if (strchr(buf, '\n') == NULL) - continue; - count++; - } - fclose(fp); - } - return count; -} - -/** - * ±N string append ¨ìÀÉ®× file «áºÝ (¤£¥[´«¦æ) - * @param file n³Q append ªºÀÉ - * @param string - * @return ¦¨¥\¶Ç¦^ 0¡A¥¢±Ñ¶Ç¦^ -1¡C - */ -int file_append_line(const char *file, const char *string) -{ - FILE *fp; - if ((fp = fopen(file, "a")) == NULL) - return -1; - flock(fileno(fp), LOCK_EX); - fputs(string, fp); - flock(fileno(fp), LOCK_UN); - fclose(fp); - return 0; -} - -/** - * ±N "$key\n" append ¨ìÀÉ®× file «áºÝ - * @param file n³Q append ªºÀÉ - * @param key ¨S¦³´«¦æªº¦r¦ê - * @return ¦¨¥\¶Ç¦^ 0¡A¥¢±Ñ¶Ç¦^ -1¡C - */ -int file_append_record(const char *file, const char *key) -{ - FILE *fp; - if (!key || !*key) return -1; - if ((fp = fopen(file, "a")) == NULL) - return -1; - flock(fileno(fp), LOCK_EX); - fputs(key, fp); - fputs("\n", fp); - flock(fileno(fp), LOCK_UN); - fclose(fp); - return 0; -} - -/** - * ¶Ç¦^ÀÉ®× file ¤¤ key ©Ò¦b¦æ¼Æ - */ -int file_find_record(const char *file, const char *key) -{ - FILE *fp; - char buf[STRLEN], *ptr; - int i = 0; - - if ((fp = fopen(file, "r")) == NULL) - return 0; - - while (fgets(buf, STRLEN, fp)) { - char *strtok_pos; - i++; - if ((ptr = strtok_r(buf, str_space, &strtok_pos)) && !strcasecmp(ptr, key)) { - fclose(fp); - return i; - } - } - fclose(fp); - return 0; -} - -/** - * ¶Ç¦^ÀÉ®× file ¤¤¬O§_¦³ key - */ -int file_exist_record(const char *file, const char *key) -{ - return file_find_record(file, key) > 0 ? 1 : 0; -} - -/** - * §R°£ÀÉ®× file ¤¤¥H string ¶}ÀYªº¦æ - * @param file n³B²zªºÀÉ®× - * @param string ´M§äªº key name - * @param case_sensitive ¬O§_n³B²z¤j¤p¼g - * @return ¦¨¥\¶Ç¦^ 0¡A¥¢±Ñ¶Ç¦^ -1¡C - */ -int -file_delete_record(const char *file, const char *string, int case_sensitive) -{ - // TODO nfp ¥Î tmpfile() ¤ñ¸û¦n¡H ¤£¹L Rename ·|ÅܺC... - FILE *fp = NULL, *nfp = NULL; - char fnew[PATHLEN]; - char buf[STRLEN + 1]; - int ret = -1, i = 0; - const size_t toklen = strlen(string); - - if (!toklen) - return 0; - - do { - snprintf(fnew, sizeof(fnew), "%s.%3.3X", file, (unsigned int)(random() & 0xFFF)); - if (access(fnew, 0) != 0) - break; - } while (i++ < 10); // max tries = 10 - - if (access(fnew, 0) == 0) return -1; // cannot create temp file. - - i = 0; - if ((fp = fopen(file, "r")) && (nfp = fopen(fnew, "w"))) { - while (fgets(buf, sizeof(buf), fp)) - { - size_t klen = strcspn(buf, str_space); - if (toklen == klen) - { - if (((case_sensitive && strncmp(buf, string, toklen) == 0) || - (!case_sensitive && strncasecmp(buf, string, toklen) == 0))) - { - // found line. skip it. - i++; - continue; - } - } - // other wise, keep the line. - fputs(buf, nfp); - } - fclose(nfp); nfp = NULL; - if (i > 0) - { - if(Rename(fnew, file) < 0) - ret = -1; - else - ret = 0; - } else { - unlink(fnew); - ret = 0; - } - } - if(fp) - fclose(fp); - if(nfp) - fclose(nfp); - return ret; -} - -/** - * ¹ï¨C¤@µ§ record °µ func ³o¥ó¨Æ¡C - * @param file - * @param func ³B²z¨Cµ§ record ªº handler¡A¬°¤@ function pointer¡C - * ²Ä¤@ӰѼƬOÀɮפ¤ªº¤@¦æ¡A²Ä¤GӰѼƬ° info¡C - * @param info ¤@ÓÃB¥~ªº°Ñ¼Æ¡C - */ -int file_foreach_entry(const char *file, int (*func)(char *, int), int info) -{ - char line[80]; - FILE *fp; - - if ((fp = fopen(file, "r")) == NULL) - return -1; - - while (fgets(line, sizeof(line), fp)) { - (*func)(line, info); - } - - fclose(fp); - return 0; -} diff --git a/mbbsd/friend.c b/mbbsd/friend.c deleted file mode 100644 index 4fbc0be3..00000000 --- a/mbbsd/friend.c +++ /dev/null @@ -1,572 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -/* ------------------------------------- */ -/* ¯S§O¦W³æ */ -/* ------------------------------------- */ - -/* Ptt ¨ä¥L¯S§O¦W³æªºÀɦW */ -char special_list[] = "list.0"; -char special_des[] = "ldes.0"; - -/* ¯S§O¦W³æªº¤W */ -static const unsigned int friend_max[8] = { - MAX_FRIEND, /* FRIEND_OVERRIDE */ - MAX_REJECT, /* FRIEND_REJECT */ - MAX_LOGIN_INFO, /* FRIEND_ALOHA */ - MAX_POST_INFO, /* FRIEND_POST */ - MAX_NAMELIST, /* FRIEND_SPECIAL */ - MAX_FRIEND, /* FRIEND_CANVOTE */ - MAX_FRIEND, /* BOARD_WATER */ - MAX_FRIEND, /* BOARD_VISABLE */ -}; -/* ÁöµM¦n¤Í¸òÃa¤H¦W³æ³£¬O * 2 ¦ý¬O¤@¦¸³Ì¦hload¨ìshm¥u¯à¦³128 */ - - -/* Ptt ¦UºØ¯S§O¦W³æªº¸Éz */ -static char * const friend_desc[8] = { - "¤Í½Ë´yz¡G", - "´c§Î´cª¬¡G", - "", - "", - "´yz¤@¤U¡G", - "§ë²¼ªÌ´yz¡G", - "´c§Î´cª¬¡G", - "¬ÝªO¦n¤Í´yz" -}; - -/* Ptt ¦UºØ¯S§O¦W³æªº¤¤¤å±Ôz */ -static char * const friend_list[8] = { - "¦n¤Í¦W³æ", - "Ãa¤H¦W³æ", - "¤W½u³qª¾", - "·s¤å³¹³qª¾", - "¨ä¥¦¯S§O¦W³æ", - "¨p¤H§ë²¼¦W³æ", - "¬ÝªO¸TÁn¦W³æ", - "¬ÝªO¦n¤Í¦W³æ" -}; - -void -setfriendfile(char *fpath, int type) -{ - if (type <= 4) /* user list Ptt */ - setuserfile(fpath, friend_file[type]); - else /* board list */ - setbfile(fpath, currboard, friend_file[type]); -} - -inline static int -friend_count(const char *fname) -{ - return file_count_line(fname); -} - -void -friend_add(const char *uident, int type, const char* des) -{ - char fpath[80]; - - setfriendfile(fpath, type); - if (friend_count(fpath) > friend_max[type]) - return; - - if ((uident[0] > ' ') && !belong(fpath, uident)) { - char buf[40] = "", buf2[256]; - char t_uident[IDLEN + 1]; - - /* Thor: avoid uident run away when get data */ - strlcpy(t_uident, uident, sizeof(t_uident)); - - if (type != FRIEND_ALOHA && type != FRIEND_POST){ - if(!des) - getdata(2, 0, friend_desc[type], buf, sizeof(buf), DOECHO); - else - getdata_str(2, 0, friend_desc[type], buf, sizeof(buf), DOECHO, des); - } - - sprintf(buf2, "%-13s%s\n", t_uident, buf); - file_append_line(fpath, buf2); - } -} - -void -friend_special(void) -{ - char genbuf[70], i, fname[70]; - FILE *fp; - friend_file[FRIEND_SPECIAL] = special_list; - for (i = 0; i <= 9; i++) { - snprintf(genbuf, sizeof(genbuf), " (" ANSI_COLOR(36) "%d" ANSI_RESET ") .. ", i); - special_des[5] = i + '0'; - setuserfile(fname, special_des); - if( (fp = fopen(fname, "r")) != NULL ){ - fgets(genbuf + 15, 40, fp); - genbuf[47] = 0; - fclose(fp); - } - move(i + 12, 0); - clrtoeol(); - outs(genbuf); - } - getdata(22, 0, "½Ð¿ï¾Ü²Ä´X¸¹¯S§O¦W³æ (0~9)[0]?", genbuf, 3, LCECHO); - if (genbuf[0] >= '0' && genbuf[0] <= '9') { - special_list[5] = genbuf[0]; - special_des[5] = genbuf[0]; - } else { - special_list[5] = '0'; - special_des[5] = '0'; - } -} - -static void -friend_append(int type, int count) -{ - char fpath[80], i, j, buf[80], sfile[80]; - FILE *fp, *fp1; - char myboard[IDLEN+1] = ""; - int boardChanged = 0; - - setfriendfile(fpath, type); - - if (currboard && *currboard) - strcpy(myboard, currboard); - - do { - move(2, 0); - clrtobot(); - outs("n¤Þ¤Jþ¤@Ó¦W³æ?\n"); - for (j = i = 0; i <= 4; i++) - if (i != type) { - ++j; - prints(" (%d) %-s\n", j, friend_list[(int)i]); - } - if (HasUserPerm(PERM_SYSOP) || currmode & MODE_BOARD) - for (; i < 8; ++i) - if (i != type) { - ++j; - prints(" (%d) %s ªOªº %s\n", j, currboard, - friend_list[(int)i]); - } - if (HasUserPerm(PERM_SYSOP)) - outs(" (S) ¿ï¾Ü¨ä¥L¬ÝªOªº¯S§O¦W³æ"); - - getdata(11, 0, "½Ð¿ï¾Ü ©Î ª½±µ[Enter] ©ñ±ó:", buf, 3, LCECHO); - if (!buf[0]) - return; - - if (HasUserPerm(PERM_SYSOP) && buf[0] == 's') - { - Select(); - boardChanged = 1; - } - - j = buf[0] - '1'; - if (j >= type) - j++; - if (!(HasUserPerm(PERM_SYSOP) || currmode & MODE_BOARD) && j >= 5) - { - if (boardChanged) - enter_board(myboard); - return; - } - } while (buf[0] < '1' || buf[0] > '9'); - - if (j == FRIEND_SPECIAL) - friend_special(); - - setfriendfile(sfile, j); - - if ((fp = fopen(sfile, "r")) != NULL) { - while (fgets(buf, 80, fp) && (unsigned)count <= friend_max[type]) { - char the_id[IDLEN + 1]; - - sscanf(buf, "%" toSTR(IDLEN) "s", the_id); - if (!file_exist_record(fpath, the_id)) { - if ((fp1 = fopen(fpath, "a"))) { - flock(fileno(fp1), LOCK_EX); - fputs(buf, fp1); - flock(fileno(fp1), LOCK_UN); - fclose(fp1); - } - } - } - fclose(fp); - } - if (boardChanged) - enter_board(myboard); -} - -static int -delete_friend_from_file(const char *file, const char *string, int case_sensitive) -{ - FILE *fp = NULL, *nfp = NULL; - char fnew[PATHLEN]; - char genbuf[STRLEN + 1]; - int ret = 0; - - sprintf(fnew, "%s.%3.3X", file, (unsigned int)(random() & 0xFFF)); - if ((fp = fopen(file, "r")) && (nfp = fopen(fnew, "w"))) { - while (fgets(genbuf, sizeof(genbuf), fp)) - if ((genbuf[0] > ' ')) { - char buf[32]; - sscanf(genbuf, " %s", buf); - if (((case_sensitive && strcmp(buf, string)) || - (!case_sensitive && strcasecmp(buf, string)))) - fputs(genbuf, nfp); - else - ret = 1; - } - Rename(fnew, file); - } - if(fp) - fclose(fp); - if(nfp) - fclose(nfp); - return ret; -} - -void -friend_delete(const char *uident, int type) -{ - char fn[STRLEN]; - setfriendfile(fn, type); - delete_friend_from_file(fn, uident, 0); -} - -static void -delete_user_friend(const char *uident, const char *thefriend, int type) -{ - char fn[PATHLEN]; - sethomefile(fn, uident, "aloha"); - delete_friend_from_file(fn, thefriend, 0); -} - -void -friend_delete_all(const char *uident, int type) -{ - char buf[PATHLEN], line[PATHLEN]; - FILE *fp; - - sethomefile(buf, uident, friend_file[type]); - - if ((fp = fopen(buf, "r")) == NULL) - return; - - while (fgets(line, sizeof(line), fp)) { - sscanf(line, "%s", buf); - delete_user_friend(buf, uident, type); - } - - fclose(fp); -} - -static void -friend_editdesc(const char *uident, int type) -{ - FILE *fp=NULL, *nfp=NULL; - char fnnew[200], genbuf[STRLEN], fn[200]; - setfriendfile(fn, type); - snprintf(fnnew, sizeof(fnnew), "%s-", fn); - if ((fp = fopen(fn, "r")) && (nfp = fopen(fnnew, "w"))) { - int length = strlen(uident); - - while (fgets(genbuf, STRLEN, fp)) { - if ((genbuf[0] > ' ') && strncmp(genbuf, uident, length)) - fputs(genbuf, nfp); - else if (!strncmp(genbuf, uident, length)) { - char buf[50] = ""; - getdata(2, 0, "קï´yz¡G", buf, 40, DOECHO); - fprintf(nfp, "%-13s%s\n", uident, buf); - } - } - Rename(fnnew, fn); - } - if(fp) - fclose(fp); - if(nfp) - fclose(nfp); -} - -inline void friend_load_real(int tosort, int maxf, - short *destn, int *destar, const char *fn) -{ - char genbuf[200]; - FILE *fp; - short nFriends = 0; - int uid, *tarray; - char *p; - - setuserfile(genbuf, fn); - if( (fp = fopen(genbuf, "r")) == NULL ){ - destar[0] = 0; - if( destn ) - *destn = 0; - } - else{ - char *strtok_pos; - tarray = (int *)malloc(sizeof(int) * maxf); - --maxf; /* ¦]¬°³Ì«á¤@Ón¶ñ 0, ©Ò¥H¥ý¦©¤@Ó¦^¨Ó */ - while( fgets(genbuf, STRLEN, fp) && nFriends < maxf ) - if( (p = strtok_r(genbuf, str_space, &strtok_pos)) && - (uid = searchuser(p, NULL)) ) - tarray[nFriends++] = uid; - fclose(fp); - - if( tosort ) - qsort(tarray, nFriends, sizeof(int), cmp_int); - if( destn ) - *destn = nFriends; - tarray[nFriends] = 0; - memcpy(destar, tarray, sizeof(int) * (nFriends + 1)); - free(tarray); - } -} - -/* type == 0 : load all */ -void friend_load(int type) -{ - if (!type || type & FRIEND_OVERRIDE) - friend_load_real(1, MAX_FRIEND, &currutmp->nFriends, - currutmp->myfriend, fn_overrides); - - if (!type || type & FRIEND_REJECT) - friend_load_real(0, MAX_REJECT, NULL, currutmp->reject, fn_reject); - - if (currutmp->friendtotal) - logout_friend_online(currutmp); - - login_friend_online(); -} - -static void -friend_water(const char *message, int type) -{ /* ¸sÅé¤ô²y added by Ptt */ - char fpath[80], line[80], userid[IDLEN + 1]; - FILE *fp; - - setfriendfile(fpath, type); - if ((fp = fopen(fpath, "r"))) { - while (fgets(line, 80, fp)) { - userinfo_t *uentp; - int tuid; - - sscanf(line, "%" toSTR(IDLEN) "s", userid); - if ((tuid = searchuser(userid, NULL)) && tuid != usernum && - (uentp = (userinfo_t *) search_ulist(tuid)) && - isvisible_uid(tuid)) - my_write(uentp->pid, message, uentp->userid, WATERBALL_PREEDIT, NULL); - } - fclose(fp); - } -} - -void -friend_edit(int type) -{ - char fpath[80], line[80], uident[IDLEN + 1]; - int count, column, dirty; - FILE *fp; - char genbuf[200]; - - if (type == FRIEND_SPECIAL) - friend_special(); - setfriendfile(fpath, type); - - if (type == FRIEND_ALOHA || type == FRIEND_POST) { - if (dashf(fpath)) { - sprintf(genbuf,"%s.old",fpath); - Copy(fpath, genbuf); - } - } - dirty = 0; - while (1) { - stand_title(friend_list[type]); - /* TODO move (0, 40) just won't really work as it hints. - * The ANSI secapes will change x coordinate. */ - move(0, 40); - prints("(¦W³æ¤W: %d ¤H)", friend_max[type]); - count = 0; - CreateNameList(); - - if ((fp = fopen(fpath, "r"))) { - move(3, 0); - column = 0; - while (fgets(genbuf, STRLEN, fp)) { - char *space; - if (genbuf[0] <= ' ') - continue; - space = strpbrk(genbuf, str_space); - if (space) *space = '\0'; - AddNameList(genbuf); - prints("%-13s", genbuf); - count++; - if (++column > 5) { - column = 0; - outc('\n'); - } - } - fclose(fp); - } - getdata(1, 0, (count ? - "(A)¼W¥[(D)§R°£(E)קï(P)¤Þ¤J(L)¸Ô²Ó¦C¥X" - "(K)§R°£¾ãÓ¦W³æ(W)¥á¤ô²y(Q)µ²§ô?[Q] " : - "(A)¼W¥[ (P)¤Þ¤J¨ä¥L¦W³æ (Q)µ²§ô?[Q] "), - uident, 3, LCECHO); - if (uident[0] == 'a') { - move(1, 0); - usercomplete(msg_uid, uident); - if (uident[0] && searchuser(uident, uident) && !InNameList(uident)) { - friend_add(uident, type, NULL); - dirty = 1; - } - } else if (uident[0] == 'p') { - friend_append(type, count); - dirty = 1; - } else if (uident[0] == 'e' && count) { - move(1, 0); - namecomplete(msg_uid, uident); - if (uident[0] && InNameList(uident)) { - friend_editdesc(uident, type); - } - } else if (uident[0] == 'd' && count) { - move(1, 0); - namecomplete(msg_uid, uident); - if (uident[0] && InNameList(uident)) { - friend_delete(uident, type); - dirty = 1; - } - } else if (uident[0] == 'l' && count) - more(fpath, YEA); - else if (uident[0] == 'k' && count) { - getdata(2, 0, "§R°£¾ã¥÷¦W³æ,½T©w¶Ü (a/N)?", uident, 3, - LCECHO); - if (uident[0] == 'a') - unlink(fpath); - dirty = 1; - } else if (uident[0] == 'w' && count) { - char wall[60]; - if (!getdata(0, 0, "¸sÅé¤ô²y:", wall, sizeof(wall), DOECHO)) - continue; - if (getdata(0, 0, "½T©w¥á¥X¸sÅé¤ô²y? [Y]", line, 4, LCECHO) && - *line == 'n') - continue; - friend_water(wall, type); - } else - break; - } - if (dirty) { - move(2, 0); - outs("§ó·s¸ê®Æ¤¤..½ÐµyÔ....."); - refresh(); - if (type == FRIEND_ALOHA || type == FRIEND_POST) { - snprintf(genbuf, sizeof(genbuf), "%s.old", fpath); - if ((fp = fopen(genbuf, "r"))) { - while (fgets(line, 80, fp)) { - sscanf(line, "%" toSTR(IDLEN) "s", uident); - sethomefile(genbuf, uident, - type == FRIEND_ALOHA ? "aloha" : "postnotify"); - del_distinct(genbuf, cuser.userid, 0); - } - fclose(fp); - } - strlcpy(genbuf, fpath, sizeof(genbuf)); - if ((fp = fopen(genbuf, "r"))) { - while (fgets(line, 80, fp)) { - sscanf(line, "%" toSTR(IDLEN) "s", uident); - sethomefile(genbuf, uident, - type == FRIEND_ALOHA ? "aloha" : "postnotify"); - add_distinct(genbuf, cuser.userid); - } - fclose(fp); - } - } else if (type == FRIEND_SPECIAL) { - genbuf[0] = 0; - setuserfile(line, special_des); - if ((fp = fopen(line, "r"))) { - fgets(genbuf, 30, fp); - fclose(fp); - } - getdata_buf(2, 0, " ½Ð¬°¦¹¯S§O¦W³æ¨ú¤@Ó²µu¦WºÙ:", genbuf, 30, - DOECHO); - if ((fp = fopen(line, "w"))) { - fputs(genbuf, fp); - fclose(fp); - } - } else if (type == BOARD_WATER) { - boardheader_t *bp = NULL; - currbid = getbnum(currboard); - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - bp = getbcache(currbid); - bp->perm_reload = now; - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); - // log_usies("SetBoard", bp->brdname); - } - friend_load(0); - } -} - -int -t_override(void) -{ - friend_edit(FRIEND_OVERRIDE); - return 0; -} - -int -t_reject(void) -{ - friend_edit(FRIEND_REJECT); - return 0; -} - -int -t_fix_aloha() -{ - char xid[IDLEN+1] = ""; - char fn[PATHLEN] = ""; - - clear(); - stand_title("×¥¿¤W¯¸³qª¾"); - - outs("³o¬O¥Î¨Ó×¥¿¬Y¨Ç¨Ï¥ÎªÌ¹J¨ì¿ù»~ªº¤W¯¸³qª¾ªº°ÝÃD¡C\n" - ANSI_COLOR(1) "¦pªG§A¨S¹J¨ì¦¹Ãþ°ÝÃD¥iª½±µÂ÷¶}¡C" ANSI_RESET "\n\n" - "¡¿¦pªG§A¹J¨ì¦³¤H¨S¦b§Aªº¤W¯¸³qª¾¦W³æ¤º¦ý¤S·|¥á¤W¯¸³qª¾¤ô²yµ¹§A¡A\n" - " ½Ð¿é¤J¥Lªº ID¡C\n"); - - move(7, 0); - usercomplete("¦³½Ö¤£¦b§Aªº³qª¾¦W³æ¤º¦ý¤S·|°e¤W¯¸³qª¾¤ô²yµ¹±z©O¡H ", xid); - - if (!xid[0]) - { - vmsg("×¥¿µ²§ô¡C"); - return 0; - } - - // check by xid - move(9, 0); - outs("Àˬd¤¤...\n"); - - // xid in my override list? - setuserfile(fn, "alohaed"); - if (belong(fn, xid)) - { - prints(ANSI_COLOR(1;32) "[%s] ½T¹ê¦b§Aªº¤W¯¸³qª¾¦W³æ¤º¡C" - "½Ð½s¿è [¤W¯¸³qª¾¦W³æ]¡C" ANSI_RESET "\n", xid); - vmsg("¤£»Ý×¥¿¡C"); - return 0; - } - - sethomefile(fn, xid, "aloha"); - if (delete_friend_from_file(fn, cuser.userid, 0)) - { - outs(ANSI_COLOR(1;33) "¤w§ä¨ì¿ù»~¨Ã×´_§¹¦¨¡C" ANSI_RESET "\n"); - } else { - outs(ANSI_COLOR(1;31) "§ä¤£¨ì¿ù»~... ¥´¿ù ID ¤F¡H" ANSI_RESET "\n"); - } - - vmsg("Y¤W¯¸³qª¾¿ù»~¤´«ùÄòµo¥Í½Ð³qª¾¯¸¤è³B²z¡C"); - return 0; -} - diff --git a/mbbsd/gamble.c b/mbbsd/gamble.c deleted file mode 100644 index 2f3e2dd7..00000000 --- a/mbbsd/gamble.c +++ /dev/null @@ -1,388 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#define MAX_ITEM 8 //³Ì¤j ½ä¶µ(item) Ó¼Æ -#define MAX_ITEM_LEN 30 //³Ì¤j ¨C¤@½ä¶µ¦W¦rªø«× -#define MAX_SUBJECT_LEN 650 //8*81 = 648 ³Ì¤j ¥DÃDªø«× - -static int -load_ticket_record(const char *direct, int ticket[]) -{ - char buf[256]; - int i, total = 0; - FILE *fp; - snprintf(buf, sizeof(buf), "%s/" FN_TICKET_RECORD, direct); - if (!(fp = fopen(buf, "r"))) - return 0; - for (i = 0; i < MAX_ITEM && fscanf(fp, "%9d ", &ticket[i])==1; i++) - total = total + ticket[i]; - fclose(fp); - return total; -} - -static int -show_ticket_data(char betname[MAX_ITEM][MAX_ITEM_LEN],const char *direct, int *price, const boardheader_t * bh) -{ - int i, count, total = 0, end = 0, ticket[MAX_ITEM] = {0, 0, 0, 0, 0, 0, 0, 0}; - FILE *fp; - char genbuf[256], t[25]; - - clear(); - if (bh) { - snprintf(genbuf, sizeof(genbuf), "%s ½ä½L", bh->brdname); - if (bh->endgamble && now < bh->endgamble && - bh->endgamble - now < 3600) { - snprintf(t, sizeof(t), - "«Ê½LË¼Æ %d ¬í", (int)(bh->endgamble - now)); - showtitle(genbuf, t); - } else - showtitle(genbuf, BBSNAME); - } else - showtitle(BBSMNAME "½ä½L", BBSNAME); - move(2, 0); - snprintf(genbuf, sizeof(genbuf), "%s/" FN_TICKET_ITEMS, direct); - if (!(fp = fopen(genbuf, "r"))) { - outs("\n¥Ø«e¨Ã¨S¦³Á|¿ì½ä½L\n"); - snprintf(genbuf, sizeof(genbuf), "%s/" FN_TICKET_OUTCOME, direct); - more(genbuf, NA); - return 0; - } - fgets(genbuf, MAX_ITEM_LEN, fp); - *price = atoi(genbuf); - for (count = 0; fgets(betname[count], MAX_ITEM_LEN, fp) && count < MAX_ITEM; count++) { - chomp(betname[count]); - } - fclose(fp); - - prints(ANSI_COLOR(32) "¯¸³W:" ANSI_RESET " 1.¥iÁʶR¥H¤U¤£¦PÃþ«¬ªº±m²¼¡C¨C±inªá " ANSI_COLOR(32) "%d" ANSI_RESET " ¤¸¡C\n" - " 2.%s\n" - " 3.¶}¼ú®É¥u¦³¤@ºØ±m²¼¤¤¼ú, ¦³ÁʶR¸Ó±m²¼ªÌ, «h¥i¨ÌÁʶRªº±i¼Æ§¡¤ÀÁ`½äª÷¡C\n" - " 4.¨Cµ§¼úª÷¥Ñ¨t²Î©â¨ú 5%% ¤§µ|ª÷%s¡C\n\n" - ANSI_COLOR(32) "%s:" ANSI_RESET, *price, - bh ? "¦¹½ä½L¥ÑªO¥Dt³dÁ|¿ì¨Ã¥B¨M©w¶}¼ú®É¶¡µ²ªG, ¯¸ªø¤£ºÞ, Ä@½äªA¿é¡C" : - "¨t²Î¨C¤Ñ 2:00 11:00 16:00 21:00 ¶}¼ú¡C", - bh ? ", ¨ä¤¤ 2% ¤Àµ¹¶}¼úªO¥D" : "", - bh ? "ªO¥D¦Ûq³W«h¤Î»¡©ú" : "«e´X¦¸¶}¼úµ²ªG"); - - - snprintf(genbuf, sizeof(genbuf), "%s/" FN_TICKET, direct); - if (!dashf(genbuf)) { - snprintf(genbuf, sizeof(genbuf), "%s/" FN_TICKET_END, direct); - end = 1; - } - show_file(genbuf, 8, -1, SHOWFILE_ALLOW_ALL); - move(15, 0); - outs(ANSI_COLOR(1;32) "¥Ø«e¤Uª`ª¬ªp:" ANSI_RESET "\n"); - - total = load_ticket_record(direct, ticket); - - outs(ANSI_COLOR(33)); - for (i = 0; i < count; i++) { - prints("%d.%-8s: %-7d", i + 1, betname[i], ticket[i]); - if (i == 3) - outc('\n'); - } - prints(ANSI_RESET "\n" ANSI_COLOR(42) " ¤Uª`Á`ª÷ÃB:" ANSI_COLOR(31) " %d ¤¸ " ANSI_RESET, total * (*price)); - if (end) { - outs("\n½ä½L¤w¸g°±¤î¤Uª`\n"); - return -count; - } - return count; -} - -static int -append_ticket_record(const char *direct, int ch, int n, int count) -{ - FILE *fp; - int ticket[8] = {0, 0, 0, 0, 0, 0, 0, 0}, i; - char genbuf[256]; - - snprintf(genbuf, sizeof(genbuf), "%s/" FN_TICKET, direct); - if (!dashf(genbuf)) - return -1; - - snprintf(genbuf, sizeof(genbuf), "%s/" FN_TICKET_USER, direct); - if ((fp = fopen(genbuf, "a"))) { - fprintf(fp, "%s %d %d\n", cuser.userid, ch, n); - fclose(fp); - } - - snprintf(genbuf, sizeof(genbuf), "%s/" FN_TICKET_RECORD, direct); - - if (!dashf(genbuf)) { - creat(genbuf, S_IRUSR | S_IWUSR); - } - - if ((fp = fopen(genbuf, "r+"))) { - - flock(fileno(fp), LOCK_EX); - - for (i = 0; i < MAX_ITEM; i++) - if (fscanf(fp, "%9d ", &ticket[i]) != 1) - break; - ticket[ch] += n; - - ftruncate(fileno(fp), 0); - rewind(fp); - for (i = 0; i < count; i++) - fprintf(fp, "%d ", ticket[i]); - fflush(fp); - - flock(fileno(fp), LOCK_UN); - fclose(fp); - } - return 0; -} - -#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 -int -ticket(int bid) -{ - int ch, end = 0; - int n, price, count; /* ÁʶR±i¼Æ¡B³æ»ù¡B¿ï¶µ¼Æ */ - char path[128], fn_ticket[128]; - char betname[MAX_ITEM][MAX_ITEM_LEN]; - boardheader_t *bh = NULL; - - STATINC(STAT_GAMBLE); - if (bid) { - bh = getbcache(bid); - setbpath(path, bh->brdname); - setbfile(fn_ticket, bh->brdname, FN_TICKET); - currbid = bid; - } else - strcpy(path, "etc/"); - - lockreturn0(TICKET, LOCK_MULTI); - while (1) { - count = show_ticket_data(betname, path, &price, bh); - if (count <= 0) { - pressanykey(); - break; - } - move(20, 0); - reload_money(); - prints(ANSI_COLOR(44) "¿ú: %-10d " ANSI_RESET "\n" ANSI_COLOR(1) "½Ð¿ï¾ÜnÁʶRªººØÃþ(1~%d)" - "[Q:Â÷¶}]" ANSI_RESET ":", cuser.money, count); - ch = igetch(); - /*-- - Tim011127 - ¬°¤F±±¨îCS°ÝÃD ¦ý¬O³oÃäÁÙ¤£¯à§¹¥þ¸Ñ¨M³o°ÝÃD, - Yuser³q¹LÀˬd¤U¥h, è¦nªO¥D¶}¼ú, ÁÙ¬O·|³y¦¨userªº³o¦¸¬ö¿ý - «Ü¦³¥i¯à¶]¨ì¤U¦¸½ä½Lªº¬ö¿ý¥h, ¤]«Ü¦³¥i¯à³QªO¥D·s¶}½ä½L®É¬~±¼ - ¤£¹L³oÃä¦Ü¤Ö¥i¥H°µ¨ìªº¬O, ³»¦h¥u·|¦³¤@µ§¸ê®Æ¬O¿ùªº - --*/ - if (ch == 'q' || ch == 'Q') - break; - ch -= '1'; - if (end || ch >= count || ch < 0) - continue; - n = 0; - ch_buyitem(price, "etc/buyticket", &n, 0); - - if (bid && !dashf(fn_ticket)) - goto doesnt_catch_up; - - if (n > 0) { - if (append_ticket_record(path, ch, n, count) < 0) - goto doesnt_catch_up; - } - } - unlockutmpmode(); - return 0; - -doesnt_catch_up: - - price = price * n; - if (price > 0) - deumoney(currutmp->uid, price); - vmsg("ªO¥D¤w¸g°±¤î¤Uª`¤F ¤£¯à½äÂP"); - unlockutmpmode(); - return -1; -} - -int -openticket(int bid) -{ - char path[MAXPATHLEN], buf[MAXPATHLEN], outcome[MAXPATHLEN]; - int i, money = 0, count, bet, price, total = 0, - ticket[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - boardheader_t *bh = getbcache(bid); - FILE *fp, *fp1; - char betname[MAX_ITEM][MAX_ITEM_LEN]; - - setbpath(path, bh->brdname); - count = -show_ticket_data(betname, path, &price, bh); - if (count == 0) { - setbfile(buf, bh->brdname, FN_TICKET_END); - unlink(buf); -//Ptt: ¦³bug - return 0; - } - lockreturn0(TICKET, LOCK_MULTI); - do { - do { - getdata(20, 0, - ANSI_COLOR(1) "¿ï¾Ü¤¤¼úªº¸¹½X(0:¤£¶}¼ú 99:¨ú®ø°h¿ú)" ANSI_RESET ":", buf, 3, LCECHO); - bet = atoi(buf); - move(0, 0); - clrtoeol(); - } while ((bet < 0 || bet > count) && bet != 99); - if (bet == 0) { - unlockutmpmode(); - return 0; - } - getdata(21, 0, ANSI_COLOR(1) "¦A¦¸½T»{¿é¤J¸¹½X" ANSI_RESET ":", buf, 3, LCECHO); - } while (bet != atoi(buf)); - - // before we fork to process, - // confirm lock status is correct. - setbfile(buf, bh->brdname, FN_TICKET_END); - setbfile(outcome, bh->brdname, FN_TICKET_LOCK); - - if(access(outcome, 0) == 0) - { - unlockutmpmode(); - vmsg("¤w¥t¦³¤H¶}¼ú¡A¨t²Îµy«á±N¦Û°Ê¤½§G¤¤¼úµ²ªG©ó¬ÝªO"); - return 0; - } - if(rename(buf, outcome) != 0) - { - unlockutmpmode(); - vmsg("µLªk·Ç³Æ¶}¼ú... ½Ð¦Ü " GLOBAL_BUGREPORT " ³ø§i¨Ãªþ¤WªO¦W¡C"); - return 0; - - } - - if (fork()) { - /* Ptt: ¥Î fork() ¨¾¤î¤£¥¿±`Â_½u¬~¿ú */ - unlockutmpmode(); - vmsg("¨t²Îµy«á±N¦Û°Ê¤½§G©ó¤¤¼úµ²ªG¬ÝªO(°Ñ¥[ªÌ¦h®Én¼Æ¤ÀÄÁ).."); - return 0; - } - close(0); - close(1); - setproctitle("open ticket"); -#ifdef CPULIMIT - { - struct rlimit rml; - rml.rlim_cur = RLIM_INFINITY; - rml.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_CPU, &rml); - } -#endif - - - bet--; /* Âন¯x°}ªºindex */ - - total = load_ticket_record(path, ticket); - setbfile(buf, bh->brdname, FN_TICKET_LOCK); - if (!(fp1 = fopen(buf, "r"))) - exit(1); - - /* ÁÙ¨S¶}§¹¼ú¤£¯à½ä³Õ ¥unmv¤@¶µ´N¦n */ - if (bet != 98) { - money = total * price; - demoney(money * 0.02); - mail_redenvelop("[½ä³õ©âÀY]", cuser.userid, money * 0.02, 'n'); - money = ticket[bet] ? money * 0.95 / ticket[bet] : 9999999; - } else { - vice(price * 10, "½ä½L°h¿ú¤âÄò¶O"); - money = price; - } - setbfile(outcome, bh->brdname, FN_TICKET_OUTCOME); - if ((fp = fopen(outcome, "w"))) { - fprintf(fp, "½ä½L»¡©ú\n"); - while (fgets(buf, sizeof(buf), fp1)) { - buf[sizeof(buf)-1] = 0; - fputs(buf, fp); - } - fprintf(fp, "¤Uª`±¡ªp\n"); - - fprintf(fp, ANSI_COLOR(33)); - for (i = 0; i < count; i++) { - fprintf(fp, "%d.%-8s: %-7d", i + 1, betname[i], ticket[i]); - if (i == 3) - fprintf(fp, "\n"); - } - fprintf(fp, ANSI_RESET "\n"); - - if (bet != 98) { - fprintf(fp, "\n\n¶}¼ú®É¶¡¡G %s \n\n" - "¶}¼úµ²ªG¡G %s \n\n" - "©Ò¦³ª÷ÃB¡G %d ¤¸ \n" - "¤¤¼ú¤ñ¨Ò¡G %d±i/%d±i (%f)\n" - "¨C±i¤¤¼ú±m²¼¥i±o %d " MONEYNAME "¹ô \n\n", - Cdatelite(&now), betname[bet], total * price, ticket[bet], total, - (float)ticket[bet] / total, money); - - fprintf(fp, "%s ½ä½L¶}¥X:%s ©Ò¦³ª÷ÃB:%d ¤¸ ¼úª÷/±i:%d ¤¸ ¾÷²v:%1.2f\n\n", - Cdatelite(&now), betname[bet], total * price, money, - total ? (float)ticket[bet] / total : 0); - } else - fprintf(fp, "\n\n½ä½L¨ú®ø°h¿ú¡G %s \n\n", Cdatelite(&now)); - - } // XXX somebody may use fp even fp==NULL - fclose(fp1); - /* - * ¥H¤U¬Oµ¹¿ú°Ê§@ - */ - setbfile(buf, bh->brdname, FN_TICKET_USER); - if ((bet == 98 || ticket[bet]) && (fp1 = fopen(buf, "r"))) { - int mybet, uid; - char userid[IDLEN + 1]; - - while (fscanf(fp1, "%s %d %d\n", userid, &mybet, &i) != EOF) { - if (bet == 98 && mybet >= 0 && mybet < count) { - if (fp) - fprintf(fp, "%s ¶R¤F %d ±i %s, °h¦^ %d ªT" MONEYNAME "¹ô\n" - ,userid, i, betname[mybet], money * i); - snprintf(buf, sizeof(buf), - "%s ½ä³õ°h¿ú! $ %d", bh->brdname, money * i); - } else if (mybet == bet) { - if (fp) - fprintf(fp, "®¥³ß %s ¶R¤F%d ±i %s, Àò±o %d ªT" MONEYNAME "¹ô\n" - ,userid, i, betname[mybet], money * i); - snprintf(buf, sizeof(buf), "%s ¤¤¼ú«¨! $ %d", bh->brdname, money * i); - } else - continue; - if ((uid = searchuser(userid, userid)) == 0) - continue; - deumoney(uid, money * i); - mail_id(userid, buf, "etc/ticket.win", BBSMNAME "½ä³õ"); - } - fclose(fp1); - } - if (fp) { - fprintf(fp, "\n--\n¡° ¶}¼ú¯¸ :" BBSNAME "(" MYHOSTNAME - ") \n¡» From: %s\n", fromhost); - fclose(fp); - } - - if (bet != 98) - snprintf(buf, sizeof(buf), "[¤½§i] %s ½ä½L¶}¼ú", bh->brdname); - else - snprintf(buf, sizeof(buf), "[¤½§i] %s ½ä½L¨ú®ø", bh->brdname); - post_file(bh->brdname, buf, outcome, "[½ä¯«]"); - post_file("Record", buf + 7, outcome, "[°¨¸ô±´¤l]"); - post_file(GLOBAL_SECURITY, buf + 7, outcome, "[°¨¸ô±´¤l]"); - - setbfile(buf, bh->brdname, FN_TICKET_RECORD); - unlink(buf); - - setbfile(buf, bh->brdname, FN_TICKET_USER); - post_file(GLOBAL_SECURITY, bh->brdname, buf, "[¤Uª`¬ö¿ý]"); - unlink(buf); - - setbfile(buf, bh->brdname, FN_TICKET_LOCK); - unlink(buf); - exit(1); - return 0; -} - -int -ticket_main(void) -{ - ticket(0); - return 0; -} diff --git a/mbbsd/go.c b/mbbsd/go.c deleted file mode 100644 index 44cf9cc8..00000000 --- a/mbbsd/go.c +++ /dev/null @@ -1,1118 +0,0 @@ -/* $Id$ */ - -#include "bbs.h" -#include <sys/socket.h> - -#define BBLANK (-1) /* ªÅ¥Õ */ -#define BWHITE (0) /* ¥Õ¤l, «á¤â */ -#define BBLACK (1) /* ¶Â¤l, ¥ý¤â */ -#define LWHITE (2) /* ¥ÕªÅ */ -#define LBLACK (3) /* ¶ÂªÅ */ - -/* only used for communicating */ -#define SETHAND (5) /* Åý¤l */ -#define CLEAN (6) /* ²M°£¦º¤l */ -#define UNCLEAN (7) /* ²M°£¿ù¤l¡A«·s¨Ó¹L*/ -#define CLEANDONE (8) /* ¶}©lp¦a */ - -#define MAX_TIME (300) - -#define BOARD_LINE_ON_SCREEN(X) ((X) + 2) - -#define BRDSIZ (19) /* ´Ñ½L³æÃä¤j¤p */ - -static const char* turn_color[] = { ANSI_COLOR(37;43), ANSI_COLOR(30;43) }; - -static const rc_t SetHandPoints[] = -{ - /* 1 */ { 0, 0}, - /* 2 */ { 3, 3}, {15, 15}, - /* 3 */ { 3, 3}, { 3, 15}, {15, 15}, - /* 4 */ { 3, 3}, { 3, 15}, {15, 3}, {15, 15}, - /* 5 */ { 3, 3}, { 3, 15}, { 9, 9}, {15, 3}, {15, 15}, - /* 6 */ { 3, 3}, { 3, 15}, { 9, 3}, { 9, 15}, {15, 3}, {15, 15}, - /* 7 */ { 3, 3}, { 3, 15}, { 9, 3}, { 9, 9}, { 9, 15}, {15, 3}, - {15, 15}, - /* 8 */ { 3, 3}, { 3, 9}, { 3, 15}, { 9, 3}, { 9, 15}, {15, 3}, - {15, 9}, {15, 15}, - /* 9 */ { 3, 3}, { 3, 9}, { 3, 15}, { 9, 3}, { 9, 9}, { 9, 15}, - {15, 3}, {15, 9}, {15, 15}, -}; - -typedef char board_t[BRDSIZ][BRDSIZ]; -typedef char (*board_p)[BRDSIZ]; - -typedef struct { - ChessStepType type; /* necessary one */ - int color; - rc_t loc; -} go_step_t; -#define RC_T_EQ(X,Y) ((X).r == (Y).r && (X).c == (Y).c) - -typedef struct { - board_t backup_board; - char game_end; - char clean_end; /* bit 1 => I, bit 2 => he */ - char need_redraw; - float feed_back; /* ¶KÁÙ */ - int eaten[2]; - int backup_eaten[2]; - rc_t forbidden[2]; /* ¥´§T¤§¸T¤â */ -} go_tag_t; -#define GET_TAG(INFO) ((go_tag_t*)(INFO)->tag) - -static char * const locE = "ABCDEFGHJKLMNOPQRST"; - -static void go_init_user(const userinfo_t* uinfo, ChessUser* user); -static void go_init_user_userec(const userec_t* urec, ChessUser* user); -static void go_init_board(board_t board); -static void go_drawline(const ChessInfo* info, int line); -static void go_movecur(int r, int c); -static int go_prepare_play(ChessInfo* info); -static int go_process_key(ChessInfo* info, int key, ChessGameResult* result); -static int go_select(ChessInfo* info, rc_t location, - ChessGameResult* result); -static void go_prepare_step(ChessInfo* info, const go_step_t* step); -static ChessGameResult go_apply_step(board_t board, const go_step_t* step); -static void go_drawstep(ChessInfo* info, const go_step_t* step); -static ChessGameResult go_post_game(ChessInfo* info); -static void go_gameend(ChessInfo* info, ChessGameResult result); -static void go_genlog(ChessInfo* info, FILE* fp, ChessGameResult result); - -const static ChessActions go_actions = { - &go_init_user, - &go_init_user_userec, - (void (*)(void*)) &go_init_board, - &go_drawline, - &go_movecur, - &go_prepare_play, - &go_process_key, - &go_select, - (void (*)(ChessInfo*, const void*)) &go_prepare_step, - (ChessGameResult (*)(void*, const void*)) &go_apply_step, - (void (*)(ChessInfo*, const void*)) &go_drawstep, - &go_post_game, - &go_gameend, - &go_genlog -}; - -const static ChessConstants go_constants = { - sizeof(go_step_t), - MAX_TIME, - BRDSIZ, - BRDSIZ, - 1, - "³ò´Ñ", - "photo_go", -#ifdef GLOBAL_GOCHESS_LOG - GLOBAL_GOCHESS_LOG, -#else - NULL, -#endif - { ANSI_COLOR(37;43), ANSI_COLOR(30;43) }, - { "¥Õ´Ñ", "¶Â´Ñ" }, -}; - -static void -go_sethand(board_t board, int n) -{ - if (n >= 2 && n <= 9) { - const int lower = n * (n - 1) / 2; - const int upper = lower + n; - int i; - for (i = lower; i < upper; ++i) - board[SetHandPoints[i].r][SetHandPoints[i].c] = BBLACK; - } -} - -/* pºâ¬Y¤lªº®ð¼Æ, recursion part of go_countlib() */ -static int -go_count(board_t board, board_t mark, int x, int y, int color) -{ - const static int diff[][2] = { - {1, 0}, {-1, 0}, {0, 1}, {0, -1} - }; - int i; - int total = 0; - - mark[x][y] = 0; - - for (i = 0; i < 4; ++i) { - int xx = x + diff[i][0]; - int yy = y + diff[i][1]; - - if (xx >= 0 && xx < BRDSIZ && yy >= 0 && yy < BRDSIZ) { - if (board[xx][yy] == BBLANK && mark[xx][yy]) { - ++total; - mark[xx][yy] = 0; - } else if (board[xx][yy] == color && mark[xx][yy]) - total += go_count(board, mark, xx, yy, color); - } - } - - return total; -} - -/* pºâ¬Y¤lªº®ð¼Æ */ -static int -go_countlib(board_t board, int x, int y, char color) -{ - int i, j; - board_t mark; - - for (i = 0; i < BRDSIZ; i++) - for (j = 0; j < BRDSIZ; j++) - mark[i][j] = 1; - - return go_count(board, mark, x, y, color); -} - -/* pºâ½L±¤W¨CÓ¤lªº®ð¼Æ */ -static void -go_eval(board_t board, int lib[][BRDSIZ], char color) -{ - int i, j; - - for (i = 0; i < 19; i++) - for (j = 0; j < 19; j++) - if (board[i][j] == color) - lib[i][j] = go_countlib(board, i, j, color); -} - -/* Àˬd¤@¨B¬O§_¦Xªk */ -static int -go_check(ChessInfo* info, const go_step_t* step) -{ - board_p board = (board_p) info->board; - int lib = go_countlib(board, step->loc.r, step->loc.c, step->color); - - if (lib == 0) { - int i, j; - int board_lib[BRDSIZ][BRDSIZ]; - go_tag_t* tag = (go_tag_t*) info->tag; - - board[step->loc.r][step->loc.c] = step->color; - go_eval(board, board_lib, !step->color); - board[step->loc.r][step->loc.c] = BBLANK; /* restore to open */ - - lib = 0; - for (i = 0; i < BRDSIZ; i++) - for (j = 0; j < BRDSIZ; j++) - if (board[i][j] == !step->color && !board_lib[i][j]) - ++lib; - - if (lib == 0 || - (lib == 1 && RC_T_EQ(step->loc, tag->forbidden[step->color]))) - return 0; - else - return 1; - } else - return 1; -} - -/* Clean up the dead chess of color `color,' summarize number of - * eaten chesses and set the forbidden point. - * - * `info' might be NULL which means no forbidden point check is - * needed and don't have to count the number of eaten chesses. - * - * Return: 1 if any chess of color `color' was eaten; 0 otherwise. */ -static int -go_examboard(board_t board, int color, ChessInfo* info) -{ - int i, j, n; - int lib[BRDSIZ][BRDSIZ]; - - rc_t dummy_rc; - rc_t *forbidden; - int dummy_eaten; - int *eaten; - - if (info) { - go_tag_t* tag = (go_tag_t*) info->tag; - forbidden = &tag->forbidden[color]; - eaten = &tag->eaten[!color]; - } else { - forbidden = &dummy_rc; - eaten = &dummy_eaten; - } - - go_eval(board, lib, color); - - forbidden->r = -1; - forbidden->c = -1; - - n = 0; - for (i = 0; i < BRDSIZ; i++) - for (j = 0; j < BRDSIZ; j++) - if (board[i][j] == color && lib[i][j] == 0) { - board[i][j] = BBLANK; - forbidden->r = i; - forbidden->c = j; - ++*eaten; - ++n; - } - - if ( n != 1 ) { - /* No or more than one chess were eaten, - * no forbidden points, then. */ - forbidden->r = -1; - forbidden->c = -1; - } - - return (n > 0); -} - -static int -go_clean(board_t board, int mark[][BRDSIZ], int x, int y, int color) -{ - const static int diff[][2] = { - {1, 0}, {-1, 0}, {0, 1}, {0, -1} - }; - int i; - int total = 1; - - mark[x][y] = 0; - board[x][y] = BBLANK; - - for (i = 0; i < 4; ++i) { - int xx = x + diff[i][0]; - int yy = y + diff[i][1]; - - if (xx >= 0 && xx < BRDSIZ && yy >= 0 && yy < BRDSIZ) { - if ((board[xx][yy] == color) && mark[xx][yy]) - total += go_clean(board, mark, xx, yy, color); - } - } - - return total; -} - -static int -go_cleandead(board_t board, int x, int y) -{ - int mark[BRDSIZ][BRDSIZ]; - int i, j; - - if (board[x][y] == BBLANK) - return 0; - - for (i = 0; i < BRDSIZ; i++) - for (j = 0; j < BRDSIZ; j++) - mark[i][j] = 1; - - return go_clean(board, mark, x, y, board[x][y]); -} - -static int -go_findcolor(board_p board, int x, int y) -{ - int k, result = 0, color[4]; - - if (board[x][y] != BBLANK) - return BBLANK; - - if (x > 0) - { - k = x; - do --k; - while ((board[k][y] == BBLANK) && (k > 0)); - color[0] = board[k][y]; - } - else - color[0] = board[x][y]; - - if (x < 18) - { - k = x; - do ++k; - while ((board[k][y] == BBLANK) && (k < 18)); - color[1] = board[k][y]; - } - else - color[1] = board[x][y]; - - if (y > 0) - { - k = y; - do --k; - while ((board[x][k] == BBLANK) && (k > 0)); - color[2] = board[x][k]; - } - else color[2] = board[x][y]; - - if (y < 18) - { - k = y; - do ++k; - while ((board[x][k] == BBLANK) && (k < 18)); - color[3] = board[x][k]; - } - else - color[3] = board[x][y]; - - for (k = 0; k < 4; k++) - { - if (color[k] == BBLANK) - continue; - else - { - result = color[k]; - break; - } - } - if (k == 4) - return BBLANK; - - for (k = 0; k < 4; k++) - { - if ((color[k] != BBLANK) && (color[k] != result)) - return BBLANK; - } - - return result; -} - -static int -go_result(ChessInfo* info) -{ - int i, j; - int count[2]; - board_p board = (board_p) info->board; - go_tag_t *tag = (go_tag_t*) info->tag; - board_t result_board; - - memcpy(result_board, board, sizeof(result_board)); - count[0] = count[1] = 0; - - for (i = 0; i < 19; i++) - for (j = 0; j < 19; j++) - if (board[i][j] == BBLANK) - { - int result = go_findcolor(board, i, j); - if (result != BBLANK) { - count[result]++; - - /* BWHITE => LWHITE, BBLACK => LBLACK */ - result_board[i][j] = result + 2; - } - } - else - count[(int) board[i][j]]++; - - memcpy(board, result_board, sizeof(result_board)); - - /* ¦º¤l¦^¶ñ */ - count[0] -= tag->eaten[1]; - count[1] -= tag->eaten[0]; - - tag->eaten[0] = count[0]; - tag->eaten[1] = count[1]; - - if (tag->feed_back < 0.01 && tag->eaten[0] == tag->eaten[1]) - return BBLANK; /* tie */ - else - return tag->eaten[0] + tag->feed_back > tag->eaten[1] ? - BWHITE : BBLACK; -} - -static char* -go_getstep(const go_step_t* step, char buf[]) -{ - const static char* const ColName = "¢Ï¢Ð¢Ñ¢Ò¢Ó¢Ô¢Õ¢Ö¢Ø¢Ù¢Ú¢Û¢Ü¢Ý¢Þ¢ß¢à¢á¢â"; - const static char* const RawName = "19181716151413121110¢¸¢·¢¶¢µ¢´¢³¢²¢±¢°"; - const static int ansi_length = sizeof(ANSI_COLOR(30;43)) - 1; - - strcpy(buf, turn_color[step->color]); - buf[ansi_length ] = ColName[step->loc.c * 2]; - buf[ansi_length + 1] = ColName[step->loc.c * 2 + 1]; - buf[ansi_length + 2] = RawName[step->loc.r * 2]; - buf[ansi_length + 3] = RawName[step->loc.r * 2 + 1]; - strcpy(buf + ansi_length + 4, ANSI_RESET " "); - - return buf; -} - -static void -go_init_tag(go_tag_t* tag) -{ - tag->game_end = 0; - tag->need_redraw = 0; - tag->feed_back = 5.5; - tag->eaten[0] = 0; - tag->eaten[1] = 0; - tag->forbidden[0].r = -1; - tag->forbidden[0].c = -1; - tag->forbidden[1].r = -1; - tag->forbidden[1].c = -1; -} - -static void -go_init_user(const userinfo_t* uinfo, ChessUser* user) -{ - strlcpy(user->userid, uinfo->userid, sizeof(user->userid)); - user->win = uinfo->go_win; - user->lose = uinfo->go_lose; - user->tie = uinfo->go_tie; -} - -static void -go_init_user_userec(const userec_t* urec, ChessUser* user) -{ - strlcpy(user->userid, urec->userid, sizeof(user->userid)); - user->win = urec->go_win; - user->lose = urec->go_lose; - user->tie = urec->go_tie; -} - -static void -go_init_board(board_t board) -{ - memset(board, BBLANK, sizeof(board_t)); -} - -static void -go_drawline(const ChessInfo* info, int line) -{ - const static char* const BoardPic[] = { - "ùÝ", "ùç", "ùç", "ùß", - "ùò", "¢q", "¢q", "ùô", - "ùò", "¢q", "¡Ï", "ùô", - "ùã", "ùí", "ùí", "ùå", - }; - const static int BoardPicIndex[] = - { 0, 1, 1, 2, 1, - 1, 1, 1, 1, 2, - 1, 1, 1, 1, 1, - 2, 1, 1, 3 }; - - board_p board = (board_p) info->board; - go_tag_t* tag = (go_tag_t*) info->tag; - - if (line == 0) { - prints(ANSI_COLOR(1;46) " ³ò´Ñ¹ï¾Ô " ANSI_COLOR(45) - "%30s VS %-20s%10s" ANSI_RESET, - info->user1.userid, info->user2.userid, - info->mode == CHESS_MODE_WATCH ? "[Æ[´Ñ¼Ò¦¡]" : ""); - } else if (line == 1) { - outs(" A B C D E F G H J K L M N O P Q R S T"); - } else if (line >= 2 && line <= 20) { - const int board_line = line - 2; - const char* const* const pics = - &BoardPic[BoardPicIndex[board_line] * 4]; - int i; - - prints("%2d" ANSI_COLOR(30;43), 21 - line); - - for (i = 0; i < BRDSIZ; ++i) - if (board[board_line][i] == BBLANK) - outs(pics[BoardPicIndex[i]]); - else - outs(bw_chess[(int) board[board_line][i]]); - - outs(ANSI_RESET); - } else if (line >= 21 && line < b_lines) - prints("%40s", ""); - else if (line == b_lines) { - if (info->mode == CHESS_MODE_VERSUS || - info->mode == CHESS_MODE_PERSONAL) { - if (tag->game_end) - outs(ANSI_COLOR(31;47) "(w)" ANSI_COLOR(30) "p¦a" ANSI_RESET); - else if (info->history.used == 0 && (info->myturn == BWHITE - || info->mode == CHESS_MODE_PERSONAL)) - outs(ANSI_COLOR(31;47) "(x)" ANSI_COLOR(30) "±Â¤l" ANSI_RESET); - } - } - - if (line == 1 || line == 2) { - int color = line - 1; /* BWHITE or BBLACK */ - - if (tag->game_end && tag->clean_end == 3) - prints(" " ANSI_COLOR(30;43) "%s" ANSI_RESET - " ¤è¤lªÅ¡G%3.1f", bw_chess[color], - tag->eaten[color] + - (color == BWHITE ? tag->feed_back : 0.0)); - else - prints(" " ANSI_COLOR(30;43) "%s" ANSI_RESET - " ¤è´£¤l¼Æ¡G%3d", bw_chess[color], tag->eaten[color]); - } else - ChessDrawExtraInfo(info, line, 3); -} - -static void -go_movecur(int r, int c) -{ - move(r + 2, c * 2 + 3); -} - -static int -go_prepare_play(ChessInfo* info) -{ - if (((go_tag_t*) info->tag)->game_end) { - strlcpy(info->warnmsg, "½Ð²M°£¦º¤l¡A¥H«Kpºâ³Ót", - sizeof(info->warnmsg)); - if (info->last_movestr[0] != ' ') - strcpy(info->last_movestr, " "); - } - - if (info->history.used == 1) - ChessDrawLine(info, b_lines); /* clear the 'x' instruction */ - - return 0; -} - -static int -go_process_key(ChessInfo* info, int key, ChessGameResult* result) -{ - go_tag_t* tag = (go_tag_t*) info->tag; - if (tag->game_end) { - if (key == 'w') { - if (!(tag->clean_end & 1)) { - go_step_t step = { CHESS_STEP_SPECIAL, CLEANDONE }; - ChessStepSend(info, &step); - tag->clean_end |= 1; - } - - if (tag->clean_end & 2 || info->mode == CHESS_MODE_PERSONAL) { - /* both sides agree */ - int winner = go_result(info); - - tag->clean_end = 3; - - if (winner == BBLANK) - *result = CHESS_RESULT_TIE; - else - *result = (winner == info->myturn ? - CHESS_RESULT_WIN : CHESS_RESULT_LOST); - - ChessRedraw(info); - return 1; - } - } else if (key == 'u') { - char buf[4]; - getdata(b_lines, 0, "¬O§_¯uªºn«·sÂI¦º¤l? (y/N)", - buf, sizeof(buf), DOECHO); - ChessDrawLine(info, b_lines); - - if (buf[0] == 'y' || buf[0] == 'Y') { - go_step_t step = { CHESS_STEP_SPECIAL, UNCLEAN }; - ChessStepSend(info, &step); - - memcpy(info->board, tag->backup_board, sizeof(tag->backup_board)); - tag->eaten[0] = tag->backup_eaten[0]; - tag->eaten[1] = tag->backup_eaten[1]; - } - } - } else if (key == 'x' && info->history.used == 0 && - ((info->mode == CHESS_MODE_VERSUS && info->myturn == BWHITE) || - info->mode == CHESS_MODE_PERSONAL)) { - char buf[4]; - int n; - - getdata(22, 43, "n±Â¦h¤Ö¤l©O(2 - 9)¡H ", buf, sizeof(buf), DOECHO); - n = atoi(buf); - - if (n >= 2 && n <= 9) { - go_step_t step = { CHESS_STEP_NORMAL, SETHAND, {n, 0} }; - - ChessStepSend(info, &step); - ChessHistoryAppend(info, &step); - - go_sethand(info->board, n); - ((go_tag_t*)info->tag)->feed_back = 0.0; - - snprintf(info->last_movestr, sizeof(info->last_movestr), - ANSI_COLOR(1) "±Â %d ¤l" ANSI_RESET, n); - ChessRedraw(info); - return 1; - } else - ChessDrawLine(info, 22); - } - return 0; -} - -static int -go_select(ChessInfo* info, rc_t location, ChessGameResult* result) -{ - board_p board = (board_p) info->board; - - if (GET_TAG(info)->game_end) { - go_step_t step = { CHESS_STEP_SPECIAL, CLEAN, location }; - if (board[location.r][location.c] == BBLANK) - return 0; - - GET_TAG(info)->eaten[!board[location.r][location.c]] += - go_cleandead(board, location.r, location.c); - - ChessStepSend(info, &step); - ChessRedraw(info); - return 0; /* don't have to return from ChessPlayFuncMy() */ - } else { - go_step_t step = { CHESS_STEP_NORMAL, info->turn, location }; - - if (board[location.r][location.c] != BBLANK) - return 0; - - if (go_check(info, &step)) { - board[location.r][location.c] = info->turn; - ChessStepSend(info, &step); - ChessHistoryAppend(info, &step); - - go_getstep(&step, info->last_movestr); - if (go_examboard(board, !info->myturn, info)) - ChessRedraw(info); - else - ChessDrawLine(info, BOARD_LINE_ON_SCREEN(location.r)); - return 1; - } else - return 0; - } -} - -static void -go_prepare_step(ChessInfo* info, const go_step_t* step) -{ - go_tag_t* tag = GET_TAG(info); - if (tag->game_end) { - /* some actions need tag so are done here */ - if (step->color == CLEAN) { - board_p board = (board_p) info->board; - tag->eaten[!board[step->loc.r][step->loc.c]] += - go_cleandead(board, step->loc.r, step->loc.c); - } else if (step->color == UNCLEAN) { - memcpy(info->board, tag->backup_board, sizeof(tag->backup_board)); - tag->eaten[0] = tag->backup_eaten[0]; - tag->eaten[1] = tag->backup_eaten[1]; - } else if (step->color == CLEANDONE) { - if (tag->clean_end & 1) { - /* both sides agree */ - int winner = go_result(info); - - tag->clean_end = 3; - - if (winner == BBLANK) - ((go_step_t*)step)->loc.r = (int) CHESS_RESULT_TIE; - else - ((go_step_t*)step)->loc.r = (int) - (winner == info->myturn ? - CHESS_RESULT_WIN : CHESS_RESULT_LOST); - - ChessRedraw(info); - } else { - ((go_step_t*)step)->color = BBLANK; /* tricks apply */ - tag->clean_end |= 2; - } - } - } else if (step->type == CHESS_STEP_NORMAL) { - if (step->color != SETHAND) { - go_getstep(step, info->last_movestr); - - memcpy(tag->backup_board, info->board, sizeof(board_t)); - tag->backup_board[step->loc.r][step->loc.c] = step->color; - - /* if any chess was eaten, wholely redraw is needed */ - tag->need_redraw = - go_examboard(tag->backup_board, !step->color, info); - } else { - snprintf(info->last_movestr, sizeof(info->last_movestr), - ANSI_COLOR(1) "±Â %d ¤l" ANSI_RESET, step->loc.r); - tag->need_redraw = 1; - ((go_tag_t*)info->tag)->feed_back = 0.0; - } - } else if (step->type == CHESS_STEP_PASS) - strcpy(info->last_movestr, "µê¤â"); -} - -static ChessGameResult -go_apply_step(board_t board, const go_step_t* step) -{ - if (step->type != CHESS_STEP_NORMAL) - return CHESS_RESULT_CONTINUE; - - switch (step->color) { - case BWHITE: - case BBLACK: - board[step->loc.r][step->loc.c] = step->color; - go_examboard(board, !step->color, NULL); - break; - - case SETHAND: - go_sethand(board, step->loc.r); - break; - - case CLEAN: - go_cleandead(board, step->loc.r, step->loc.c); - break; - - case CLEANDONE: - /* should be agreed by both sides, [see go_prepare_step()] */ - return (ChessGameResult) step->loc.r; - } - return CHESS_RESULT_CONTINUE; -} - -static void -go_drawstep(ChessInfo* info, const go_step_t* step) -{ - go_tag_t* tag = GET_TAG(info); - if (tag->game_end || tag->need_redraw) - ChessRedraw(info); - else - ChessDrawLine(info, BOARD_LINE_ON_SCREEN(step->loc.r)); -} - -static ChessGameResult -go_post_game(ChessInfo* info) -{ - extern ChessGameResult ChessPlayFuncMy(ChessInfo* info); - - go_tag_t *tag = (go_tag_t*) info->tag; - ChessTimeLimit *orig_limit = info->timelimit; - ChessGameResult result; - - info->timelimit = NULL; - info->turn = info->myturn; - strcpy(info->warnmsg, "½ÐÂI°£¦º¤l"); - ChessDrawLine(info, CHESS_DRAWING_WARN_ROW); - - memcpy(tag->backup_board, info->board, sizeof(tag->backup_board)); - tag->game_end = 1; - tag->clean_end = 0; - tag->backup_eaten[0] = tag->eaten[0]; - tag->backup_eaten[1] = tag->eaten[1]; - - ChessDrawLine(info, b_lines); /* 'w' instruction */ - - while ((result = ChessPlayFuncMy(info)) == CHESS_RESULT_CONTINUE); - - ChessRedraw(info); - - info->timelimit = orig_limit; - - return result; -} - -static void -go_gameend(ChessInfo* info, ChessGameResult result) -{ - if (info->mode == CHESS_MODE_VERSUS) { - ChessUser* const user1 = &info->user1; - /* ChessUser* const user2 = &info->user2; */ - - user1->lose--; - if (result == CHESS_RESULT_WIN) { - user1->win++; - currutmp->go_win++; - } else if (result == CHESS_RESULT_LOST) { - user1->lose++; - currutmp->go_lose++; - } else { - user1->tie++; - currutmp->go_tie++; - } - - cuser.go_win = user1->win; - cuser.go_lose = user1->lose; - cuser.go_tie = user1->tie; - - passwd_update(usernum, &cuser); - } else if (info->mode == CHESS_MODE_REPLAY) { - free(info->board); - free(info->tag); - } -} - -static void -go_genlog(ChessInfo* info, FILE* fp, ChessGameResult result) -{ - const static char ColName[] = "ABCDEFGHJKLMNOPQRST"; - const int nStep = info->history.used; - char buf[ANSILINELEN] = ""; - int i, x, y; - int sethand = 0; - - if (nStep > 0) { - const go_step_t* const step = - (const go_step_t*) ChessHistoryRetrieve(info, 0); - if (step->color == SETHAND) - sethand = step->loc.r; - } - - getyx(&y, &x); - for (i = 1; i <= 22; i++) - { - move(i, 0); - inansistr(buf, sizeof(buf)-1); - fprintf(fp, "%s\n", buf); - } - move(y, x); - - fprintf(fp, "\n"); - fprintf(fp, "«ö z ¥i¶i¤J¥´ÃмҦ¡\n"); - fprintf(fp, "\n"); - - if (sethand) { - fprintf(fp, "[ 1] ±Â %d ¤l\n ", sethand); - i = 1; - } else - i = 0; - - for (; i < nStep; ++i) { - const go_step_t* const step = - (const go_step_t*) ChessHistoryRetrieve(info, i); - if (step->type == CHESS_STEP_NORMAL) - fprintf(fp, "[%3d]%s => %c%-4d", i + 1, bw_chess[step->color], - ColName[step->loc.c], 19 - step->loc.r); - else if (step->type == CHESS_STEP_PASS) - fprintf(fp, "[%3d]%s => µê¤â ", i + 1, bw_chess[(i + 1) % 2]); - else - break; - if (i % 5 == 4) - fputc('\n', fp); - } - - fprintf(fp, - "\n\n¡m¥H¤U¬° sgf ®æ¦¡´ÑÃСn\n<golog>\n(;GM[1]" - "GN[%s-%s(W) Ptt]\n" - "SZ[19]HA[%d]PB[%s]PW[%s]\n" - "PC[FPG BBS/Ptt BBS: ptt.cc]\n", - info->user1.userid, info->user2.userid, - sethand, - info->user1.userid, info->user2.userid); - - if (sethand) { - const int lower = sethand * (sethand - 1) / 2; - const int upper = lower + sethand; - int j; - fputs("AB", fp); - for (j = lower; j < upper; ++j) - fprintf(fp, "[%c%c]", - SetHandPoints[j].c + 'a', - SetHandPoints[j].r + 'a'); - fputc('\n', fp); - } - - for (i = (sethand ? 1 : 0); i < nStep; ++i) { - const go_step_t* const step = - (const go_step_t*) ChessHistoryRetrieve(info, i); - if (step->type == CHESS_STEP_NORMAL) - fprintf(fp, ";%c[%c%c]", - step->color == BWHITE ? 'W' : 'B', - step->loc.c + 'a', - step->loc.r + 'a'); - else if (step->type == CHESS_STEP_PASS) - fprintf(fp, ";%c[] ", i % 2 ? 'W' : 'B'); - else - break; - if (i % 10 == 9) - fputc('\n', fp); - } - fprintf(fp, ";)\n<golog>\n\n"); -} - -void -gochess(int s, ChessGameMode mode) -{ - ChessInfo* info = NewChessInfo(&go_actions, &go_constants, s, mode); - board_t board; - go_tag_t tag; - - go_init_board(board); - go_init_tag(&tag); - - info->board = board; - info->tag = &tag; - - info->cursor.r = 9; - info->cursor.c = 9; - - if (mode == CHESS_MODE_WATCH) - setutmpmode(CHESSWATCHING); - else - setutmpmode(UMODE_GO); - currutmp->sig = SIG_GO; - - ChessPlay(info); - - DeleteChessInfo(info); -} - -int -gochess_main(void) -{ - return ChessStartGame('g', SIG_GO, "³ò´Ñ"); -} - -int -gochess_personal(void) -{ - gochess(0, CHESS_MODE_PERSONAL); - return 0; -} - -int -gochess_watch(void) -{ - return ChessWatchGame(&gochess, UMODE_GO, "³ò´Ñ"); -} - -static int -mygetc(FILE* fp, char* buf, int* idx, int len) -{ - for (;;) { - while (buf[*idx] && isspace(buf[*idx])) ++*idx; - - if (buf[*idx]) { - ++*idx; - return buf[*idx - 1]; - } - - if (fgets(buf, len, fp) == NULL) - return EOF; - - if (strcmp(buf, "<golog>\n") == 0) - return EOF; - - *idx = 0; - } -} - -ChessInfo* -gochess_replay(FILE* fp) -{ - ChessInfo *info; - int ch; - char userid[2][IDLEN + 1] = { "", "" }; - char sethand_str[4] = ""; - char *recording = NULL; - char *record_end = NULL; - go_step_t step; - - /* for mygetc */ - char buf[512] = ""; - int idx = 0; - -#define GETC() mygetc(fp, buf, &idx, sizeof(buf)) - - /* sgf file started with "(;" */ - if (GETC() != '(' || GETC() != ';') - return NULL; - - /* header info */ - while ((ch = GETC()) != EOF && ch != ';') { - if (ch == '[') { - if (recording) { - while ((ch = GETC()) != EOF && ch != ']') - if (recording < record_end) - *recording++ = ch; - *recording = 0; - recording = NULL; - } else - while ((ch = GETC()) != EOF && ch != ']') - continue; - - if (ch == EOF) - break; - } else if (ch == ';') /* next stage */ - break; - else { - int ch2 = GETC(); - - if (ch2 == EOF) { - ch = EOF; - break; - } - - if (ch == 'P') { - if (ch2 == 'B') { - recording = userid[BBLACK]; - record_end = userid[BBLACK] + IDLEN; - } else if (ch2 == 'W') { - recording = userid[BWHITE]; - record_end = userid[BWHITE] + IDLEN; - } - } else if (ch == 'H') { - if (ch2 == 'A') { - recording = sethand_str; - record_end = sethand_str + sizeof(sethand_str) - 1; - } - } - } - } - - if (ch == EOF) - return NULL; - - info = NewChessInfo(&go_actions, &go_constants, - 0, CHESS_MODE_REPLAY); - - /* filling header information to info */ - if (userid[BBLANK][0]) { - userec_t rec; - if (getuser(userid[BBLANK], &rec)) - go_init_user_userec(&rec, &info->user1); - } - - if (userid[BWHITE][0]) { - userec_t rec; - if (getuser(userid[BWHITE], &rec)) - go_init_user_userec(&rec, &info->user2); - } - - if (sethand_str[0]) { - int sethand = atoi(sethand_str); - if (sethand >= 2 && sethand <= 9) { - step.type = CHESS_STEP_NORMAL; - step.color = SETHAND; - step.loc.r = sethand; - ChessHistoryAppend(info, &step); - } - } - - /* steps, ends with ")" */ - while ((ch = GETC()) != EOF && ch != ')') { - if (ch == ';') - ChessHistoryAppend(info, &step); - else if (ch == 'B') - step.color = BBLACK; - else if (ch == 'W') - step.color = BWHITE; - else if (ch == '[') { - ch = GETC(); - if (ch == EOF) - break; - else if (ch == ']') { - step.type = CHESS_STEP_PASS; - continue; - } else - step.loc.c = ch - 'a'; - - ch = GETC(); - if (ch == EOF) - break; - else if (ch == ']') { - step.type = CHESS_STEP_PASS; - continue; - } else - step.loc.r = ch - 'a'; - - while ((ch = GETC()) != EOF && ch != ']'); - - if (step.loc.r < 0 || step.loc.r >= BRDSIZ || - step.loc.c < 0 || step.loc.c >= BRDSIZ) - step.type = CHESS_STEP_PASS; - else - step.type = CHESS_STEP_NORMAL; - } - } - - info->board = malloc(sizeof(board_t)); - info->tag = malloc(sizeof(go_tag_t)); - - go_init_board(info->board); - go_init_tag(info->tag); - - return info; - -#undef GETC -} diff --git a/mbbsd/gomo.c b/mbbsd/gomo.c deleted file mode 100644 index 90f72c63..00000000 --- a/mbbsd/gomo.c +++ /dev/null @@ -1,590 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -#include "gomo.h" - -#define QCAST int (*)(const void *, const void *) -#define BOARD_LINE_ON_SCREEN(X) ((X) + 2) - -static const char* turn_color[] = { ANSI_COLOR(37;43), ANSI_COLOR(30;43) }; - -enum Turn { - WHT = 0, - BLK -}; - -typedef struct { - ChessStepType type; /* necessary one */ - int color; - rc_t loc; -} gomo_step_t; - -typedef char board_t[BRDSIZ][BRDSIZ]; -typedef char (*board_p)[BRDSIZ]; - -static void gomo_init_user(const userinfo_t* uinfo, ChessUser* user); -static void gomo_init_user_userec(const userec_t* urec, ChessUser* user); -static void gomo_init_board(board_t board); -static void gomo_drawline(const ChessInfo* info, int line); -static void gomo_movecur(int r, int c); -static int gomo_prepare_play(ChessInfo* info); -static int gomo_select(ChessInfo* info, rc_t location, - ChessGameResult* result); -static void gomo_prepare_step(ChessInfo* info, const gomo_step_t* step); -static ChessGameResult gomo_apply_step(board_t board, const gomo_step_t* step); -static void gomo_drawstep(ChessInfo* info, const gomo_step_t* step); -static void gomo_gameend(ChessInfo* info, ChessGameResult result); -static void gomo_genlog(ChessInfo* info, FILE* fp, ChessGameResult result); - -const static ChessActions gomo_actions = { - &gomo_init_user, - &gomo_init_user_userec, - (void (*)(void*)) &gomo_init_board, - &gomo_drawline, - &gomo_movecur, - &gomo_prepare_play, - NULL, /* process_key */ - &gomo_select, - (void (*)(ChessInfo*, const void*)) &gomo_prepare_step, - (ChessGameResult (*)(void*, const void*)) &gomo_apply_step, - (void (*)(ChessInfo*, const void*)) &gomo_drawstep, - NULL, /* post_game */ - &gomo_gameend, - &gomo_genlog -}; - -const static ChessConstants gomo_constants = { - sizeof(gomo_step_t), - MAX_TIME, - BRDSIZ, - BRDSIZ, - 0, - "¤¤l´Ñ", - "photo_fivechess", -#ifdef GLOBAL_FIVECHESS_LOG - GLOBAL_FIVECHESS_LOG, -#else - NULL, -#endif - { ANSI_COLOR(37;43), ANSI_COLOR(30;43) }, - { "¥Õ´Ñ", "¶Â´Ñ, ¦³¸T¤â" }, -}; - -/* pattern and advance map */ - -static int -intrevcmp(const void *a, const void *b) -{ - return (*(int *)b - *(int *)a); -} - -// ¥H (x,y) ¬°°_ÂI, ¤è¦V (dx,dy), ¶Ç¦^¥H bit ªí¥Ü¬Û¾Fþ´X®æ¦³¤l -// ¦p 10111 ªí¥Ü¸Ó¤è¦V¬Û¾F 1,2,3 ¦³¤l, 4 ªÅ¦a -// ³Ì°ª¦ì 1 ªí¥Ü¹ï¤èªº¤l, ©Î¬OÀð -/* x,y: 0..BRDSIZ-1 ; color: CBLACK,CWHITE ; dx,dy: -1,0,+1 */ -static int -gomo_getindex(board_t ku, int x, int y, int color, int dx, int dy) -{ - int i, k, n; - for (n = -1, i = 0, k = 1; i < 5; i++, k*=2) { - x += dx; - y += dy; - - if ((x < 0) || (x >= BRDSIZ) || (y < 0) || (y >= BRDSIZ)) { - n += k; - break; - } else if (ku[x][y] != BBLANK) { - n += k; - if (ku[x][y] != color) - break; - } - } - - if (i >= 5) - n += k; - - return n; -} - -ChessGameResult -chkwin(int style, int limit) -{ - if (style == 0x0c) - return CHESS_RESULT_WIN; - else if (limit == 0) { - if (style == 0x0b) - return CHESS_RESULT_WIN; - return CHESS_RESULT_CONTINUE; - } - if ((style < 0x0c) && (style > 0x07)) - return CHESS_RESULT_LOST; - return CHESS_RESULT_CONTINUE; -} - -static int getstyle(board_t ku, int x, int y, int color, int limit); -/* x,y: 0..BRDSIZ-1 ; color: CBLACK,CWHITE ; limit:1,0 ; dx,dy: 0,1 */ -static int -dirchk(board_t ku, int x, int y, int color, int limit, int dx, int dy) -{ - int le, ri, loc, style = 0; - - le = gomo_getindex(ku, x, y, color, -dx, -dy); - ri = gomo_getindex(ku, x, y, color, dx, dy); - - loc = (le > ri) ? (((le * (le + 1)) >> 1) + ri) : - (((ri * (ri + 1)) >> 1) + le); - - style = pat_gomoku[loc]; - - if (limit == 0) - return (style & 0x0f); - - style >>= 4; - - if ((style == 3) || (style == 2)) { - int i, n = 0, tmp, nx, ny; - - n = adv_gomoku[loc / 2]; - - if(loc%2==0) - n/=16; - else - n%=16; - - ku[x][y] = color; - - for (i = 0; i < 2; i++) { - if ((tmp = (i == 0) ? (-(n >> 2)) : (n & 3)) != 0) { - nx = x + (le > ri ? 1 : -1) * tmp * dx; - ny = y + (le > ri ? 1 : -1) * tmp * dy; - - if ((dirchk(ku, nx, ny, color, 0, dx, dy) == 0x06) && - (chkwin(getstyle(ku, nx, ny, color, limit), limit) >= 0)) - break; - } - } - if (i >= 2) - style = 0; - ku[x][y] = BBLANK; - } - return style; -} - -/* ¨Ò¥~=F ¿ù»~=E ¦³¤l=D ³s¤=C ³s¤»=B Âù¥|=A ¥|¥|=9 ¤T¤T=8 */ -/* ¥|¤T=7 ¬¡¥|=6 Â_¥|=5 ¦º¥|=4 ¬¡¤T=3 Â_¤T=2 «O¯d=1 µL®Ä=0 */ - -/* x,y: 0..BRDSIZ-1 ; color: CBLACK,CWHITE ; limit: 1,0 */ -static int -getstyle(board_t ku, int x, int y, int color, int limit) -{ - int i, j, dir[4], style; - - if ((x < 0) || (x >= BRDSIZ) || (y < 0) || (y >= BRDSIZ)) - return 0x0f; - if (ku[x][y] != BBLANK) - return 0x0d; - - // (-1,1), (0,1), (1,0), (1,1) - for (i = 0; i < 4; i++) - dir[i] = dirchk(ku, x, y, color, limit, i ? (i >> 1) : -1, i ? (i & 1) : 1); - - qsort(dir, 4, sizeof(int), (QCAST)intrevcmp); - - if ((style = dir[0]) >= 2) { - for (i = 1, j = 6 + (limit ? 1 : 0); i < 4; i++) { - if ((style > j) || (dir[i] < 2)) - break; - if (dir[i] > 3) - style = 9; - else if ((style < 7) && (style > 3)) - style = 7; - else - style = 8; - } - } - return style; -} - -static char* -gomo_move_warn(int style, char buf[]) -{ - char *xtype[] = { - ANSI_COLOR(1;31) "¸õ¤T" ANSI_RESET, - ANSI_COLOR(1;31) "¬¡¤T" ANSI_RESET, - ANSI_COLOR(1;31) "¦º¥|" ANSI_RESET, - ANSI_COLOR(1;31) "¸õ¥|" ANSI_RESET, - ANSI_COLOR(1;31) "¬¡¥|" ANSI_RESET, - ANSI_COLOR(1;31) "¥|¤T" ANSI_RESET, - ANSI_COLOR(1;31) "Âù¤T" ANSI_RESET, - ANSI_COLOR(1;31) "Âù¥|" ANSI_RESET, - ANSI_COLOR(1;31) "Âù¥|" ANSI_RESET, - ANSI_COLOR(1;31) "³s¤»" ANSI_RESET, - ANSI_COLOR(1;31) "³s¤" ANSI_RESET - }; - if (style > 1 && style < 13) - return strcpy(buf, xtype[style - 2]); - else - return NULL; -} - -static void -gomoku_usr_put(userec_t* userec, const ChessUser* user) -{ - userec->five_win = user->win; - userec->five_lose = user->lose; - userec->five_tie = user->tie; -} - -static char* -gomo_getstep(const gomo_step_t* step, char buf[]) -{ - const static char* const ColName = "¢Ï¢Ð¢Ñ¢Ò¢Ó¢Ô¢Õ¢Ö¢×¢Ø¢Ù¢Ú¢Û¢Ü"; - const static char* const RawName = "151413121110¢¸¢·¢¶¢µ¢´¢³¢²¢±¢°"; - const static int ansi_length = sizeof(ANSI_COLOR(30;43)) - 1; - - strcpy(buf, turn_color[step->color]); - buf[ansi_length ] = ColName[step->loc.c * 2]; - buf[ansi_length + 1] = ColName[step->loc.c * 2 + 1]; - buf[ansi_length + 2] = RawName[step->loc.r * 2]; - buf[ansi_length + 3] = RawName[step->loc.r * 2 + 1]; - strcpy(buf + ansi_length + 4, ANSI_RESET); - - return buf; -} - -static void -gomo_init_user(const userinfo_t* uinfo, ChessUser* user) -{ - strlcpy(user->userid, uinfo->userid, sizeof(user->userid)); - user->win = uinfo->five_win; - user->lose = uinfo->five_lose; - user->tie = uinfo->five_tie; -} - -static void -gomo_init_user_userec(const userec_t* urec, ChessUser* user) -{ - strlcpy(user->userid, urec->userid, sizeof(user->userid)); - user->win = urec->five_win; - user->lose = urec->five_lose; - user->tie = urec->five_tie; -} - -static void -gomo_init_board(board_t board) -{ - memset(board, BBLANK, sizeof(board_t)); -} - -static void -gomo_drawline(const ChessInfo* info, int line) -{ - const static char* const BoardPic[] = { - "ùÝ", "ùç", "ùç", "ùß", - "ùò", "¢q", "¢q", "ùô", - "ùò", "¢q", "¡Ï", "ùô", - "ùã", "ùí", "ùí", "ùå", - }; - const static int BoardPicIndex[] = - { 0, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 3 }; - - board_p board = (board_p) info->board; - - if (line == 0) { - prints(ANSI_COLOR(1;46) " ¤¤l´Ñ¹ï¾Ô " ANSI_COLOR(45) - "%30s VS %-20s%10s" ANSI_RESET, - info->user1.userid, info->user2.userid, - info->mode == CHESS_MODE_WATCH ? "[Æ[´Ñ¼Ò¦¡]" : ""); - } else if (line == 1) { - outs(" A B C D E F G H I J K L M N"); - } else if (line >= 2 && line <= 16) { - const int board_line = line - 2; - const char* const* const pics = - &BoardPic[BoardPicIndex[board_line] * 4]; - int i; - - prints("%3d" ANSI_COLOR(30;43), 17 - line); - - for (i = 0; i < BRDSIZ; ++i) - if (board[board_line][i] == -1) - outs(pics[BoardPicIndex[i]]); - else - outs(bw_chess[(int) board[board_line][i]]); - - outs(ANSI_RESET); - } else if (line >= 17 && line < b_lines) - prints("%33s", ""); - - ChessDrawExtraInfo(info, line, 8); -} - -static void -gomo_movecur(int r, int c) -{ - move(r + 2, c * 2 + 3); -} - -static int -gomo_prepare_play(ChessInfo* info) -{ - if (!gomo_move_warn(*(int*) info->tag, info->warnmsg)) - info->warnmsg[0] = 0; - - return 0; -} - -static int -gomo_select(ChessInfo* info, rc_t location, ChessGameResult* result) -{ - board_p board = (board_p) info->board; - gomo_step_t step; - - if(board[location.r][location.c] != BBLANK) - return 0; - - *(int*) info->tag = getstyle(board, location.r, location.c, - info->turn, info->turn == BLK); - *result = chkwin(*(int*) info->tag, info->turn == BLK); - - board[location.r][location.c] = info->turn; - - step.type = CHESS_STEP_NORMAL; - step.color = info->turn; - step.loc = location; - gomo_getstep(&step, info->last_movestr); - - ChessHistoryAppend(info, &step); - ChessStepSend(info, &step); - gomo_drawstep(info, &step); - - return 1; -} - -static void -gomo_prepare_step(ChessInfo* info, const gomo_step_t* step) -{ - if (step->type == CHESS_STEP_NORMAL) { - gomo_getstep(step, info->last_movestr); - *(int*) info->tag = getstyle(info->board, step->loc.r, step->loc.c, - step->color, step->color == BLK); - info->cursor = step->loc; - } -} - -static ChessGameResult -gomo_apply_step(board_t board, const gomo_step_t* step) -{ - int style; - - style = getstyle(board, step->loc.r, step->loc.c, - step->color, step->color == BLK); - board[step->loc.r][step->loc.c] = step->color; - return chkwin(style, step->color == BLK); -} - -static void -gomo_drawstep(ChessInfo* info, const gomo_step_t* step) -{ - ChessDrawLine(info, BOARD_LINE_ON_SCREEN(step->loc.r)); -} - -static void -gomo_gameend(ChessInfo* info, ChessGameResult result) -{ - if (info->mode == CHESS_MODE_VERSUS) { - ChessUser* const user1 = &info->user1; - /* ChessUser* const user2 = &info->user2; */ - - user1->lose--; - if (result == CHESS_RESULT_WIN) { - user1->win++; - currutmp->five_win++; - } else if (result == CHESS_RESULT_LOST) { - user1->lose++; - currutmp->five_lose++; - } else { - user1->tie++; - currutmp->five_tie++; - } - - cuser.five_win = user1->win; - cuser.five_lose = user1->lose; - cuser.five_tie = user1->tie; - - passwd_update(usernum, &cuser); - } else if (info->mode == CHESS_MODE_REPLAY) { - free(info->board); - free(info->tag); - } -} - -static void -gomo_genlog(ChessInfo* info, FILE* fp, ChessGameResult result) -{ - char buf[ANSILINELEN] = ""; - const int nStep = info->history.used; - int i, x, y; - - getyx(&y, &x); - for (i = 1; i <= 18; i++) - { - move(i, 0); - inansistr(buf, sizeof(buf)-1); - fprintf(fp, "%s\n", buf); - } - move(y, x); - - fprintf(fp, "\n"); - fprintf(fp, "«ö z ¥i¶i¤J¥´ÃмҦ¡\n"); - fprintf(fp, "\n"); - - fprintf(fp, "<gomokulog>\nblack:%s\nwhite:%s\n", - info->myturn ? info->user1.userid : info->user2.userid, - info->myturn ? info->user2.userid : info->user1.userid); - - for (i = 0; i < nStep; ++i) { - const gomo_step_t* const step = - (const gomo_step_t*) ChessHistoryRetrieve(info, i); - if (step->type == CHESS_STEP_NORMAL) - fprintf(fp, "[%2d]%s ==> %c%-5d", i + 1, bw_chess[step->color], - 'A' + step->loc.c, 15 - step->loc.r); - else - break; - if (i % 2) - fputc('\n', fp); - } - - if (i % 2) - fputc('\n', fp); - fputs("</gomokulog>\n", fp); -} - -static int gomo_loadlog(FILE *fp, ChessInfo *info) -{ - char buf[256]; - -#define INVALID_ROW(R) ((R) < 0 || (R) >= BRDSIZ) -#define INVALID_COL(C) ((C) < 0 || (C) >= BRDSIZ) - while (fgets(buf, sizeof(buf), fp)) { - if (strcmp("</gomokulog>\n", buf) == 0) - return 1; - else if (strncmp("black:", buf, 6) == 0 || - strncmp("white:", buf, 6) == 0) { - /* /(black|white):([a-zA-Z0-9]+)/; $2 */ - userec_t rec; - ChessUser *user = (buf[0] == 'b' ? &info->user1 : &info->user2); - - chomp(buf); - if (getuser(buf + 6, &rec)) - gomo_init_user_userec(&rec, user); - } else if (buf[0] == '[') { - /* "[ 1]¡´ ==> H8 [ 2]¡³ ==> H9" */ - gomo_step_t step = { CHESS_STEP_NORMAL }; - int c, r; - const char *p = buf; - int i; - - for(i=0; i<2; i++) { - p = strchr(p, '>'); - - if (p == NULL) break; - - ++p; /* skip '>' */ - while (*p && isspace(*p)) ++p; - if (!*p) break; - - /* i=0, p -> "H8 ..." */ - /* i=1, p -> "H9\n" */ - c = p[0] - 'A'; - r = BRDSIZ - atoi(p + 1); - - if (INVALID_COL(c) || INVALID_ROW(r)) - break; - - step.color = i==0? BLK : WHT; - step.loc.r = r; - step.loc.c = c; - ChessHistoryAppend(info, &step); - } - } - } -#undef INVALID_ROW -#undef INVALID_COL - return 0; -} - - -void -gomoku(int s, ChessGameMode mode) -{ - ChessInfo* info = NewChessInfo(&gomo_actions, &gomo_constants, s, mode); - board_t board; - int tag; - - gomo_init_board(board); - tag = 0; - - info->board = board; - info->tag = &tag; - - info->cursor.r = 7; - info->cursor.c = 7; - - if (info->mode == CHESS_MODE_VERSUS) { - /* Assume that info->user1 is me. */ - info->user1.lose++; - passwd_query(usernum, &cuser); - gomoku_usr_put(&cuser, &info->user1); - passwd_update(usernum, &cuser); - } - - if (mode == CHESS_MODE_WATCH) - setutmpmode(CHESSWATCHING); - else - setutmpmode(M_FIVE); - currutmp->sig = SIG_GOMO; - - ChessPlay(info); - - DeleteChessInfo(info); -} - -int -gomoku_main(void) -{ - return ChessStartGame('f', SIG_GOMO, "¤¤l´Ñ"); -} - -int -gomoku_personal(void) -{ - gomoku(0, CHESS_MODE_PERSONAL); - return 0; -} - -int -gomoku_watch(void) -{ - return ChessWatchGame(&gomoku, M_FIVE, "¤¤l´Ñ"); -} - -ChessInfo* -gomoku_replay(FILE* fp) -{ - ChessInfo *info; - - info = NewChessInfo(&gomo_actions, &gomo_constants, - 0, CHESS_MODE_REPLAY); - - if(!gomo_loadlog(fp, info)) { - DeleteChessInfo(info); - return NULL; - } - - info->board = malloc(sizeof(board_t)); - info->tag = malloc(sizeof(int)); - - gomo_init_board(info->board); - *(int*)(info->tag) = 0; - - return info; -} diff --git a/mbbsd/guess.c b/mbbsd/guess.c deleted file mode 100644 index c5408b88..00000000 --- a/mbbsd/guess.c +++ /dev/null @@ -1,369 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -#define LOGPASS BBSHOME "/etc/winguess.log" - -static void -show_table(char TABLE[], char ifcomputer) -{ - int i; - - move(0, 35); - outs(ANSI_COLOR(1;44;33) " ¡i ²q¼Æ¦r ¡j " ANSI_RESET); - move(8, 1); - outs(ANSI_COLOR(1;44;36) "¥Ø «e ¿ ²v" ANSI_RESET "\n"); - outs(ANSI_COLOR(1;33) "=================" ANSI_RESET "\n"); - if (ifcomputer) { - outs("Ĺ¹q¸£: 2 ¿\n"); - outs("¿é¹q¸£: 0 ¿\n"); - } else { - for (i = 1; i <= 6; i++) - prints("²Ä%d¦¸, %02d¿\n", i, TABLE[i]); - } - outs(ANSI_COLOR(33) "=================" ANSI_RESET); -} - -static int -get_money(void) -{ - int money, i; - char data[20]; - - move(1, 0); - prints("±z¥Ø«e¦³:%d " MONEYNAME "$", cuser.money); - do { - getdata(2, 0, "n½ä¦h¤Ö(5-10©Î«öqÂ÷¶}): ", data, 9, LCECHO); - money = 0; - if (data[0] == 'q' || data[0] == 'Q') { - unlockutmpmode(); - return 0; - } - for (i = 0; data[i]; i++) - if (data[i] < '0' || data[i] > '9') { - money = -1; - break; - } - if (money != -1) { - money = atoi(data); - reload_money(); - if (money > cuser.money || money <= 4 || money > 10 || - money < 1) - money = -1; - } - } while (money == -1); - move(1, 0); - clrtoeol(); - reload_money(); - prints("±z¥Ø«e¦³:%d " MONEYNAME "$", cuser.money - money); - return money; -} - -static int -check_data(const char *str) -{ - int i, j; - - if (strlen(str) != 4) - return -1; - for (i = 0; i < 4; i++) - if (str[i] < '0' || str[i] > '9') - return -1; - for (i = 0; i < 4; i++) - for (j = i + 1; j < 4; j++) - if (str[i] == str[j]) - return -1; - return 1; -} - -static char * -get_data(char data[5], int count) -{ - while (1) { - getdata(6, 0, "¿é¤J¥|¦ì¼Æ¦r(¤£«½Æ): ", data, 5, LCECHO); - if (check_data(data) == 1) - break; - } - return data; -} - -static int -guess_play(const char *data, const char *answer, int count) -{ - int A_num = 0, B_num = 0; - int i, j; - - for (i = 0; i < 4; i++) { - if (data[i] == answer[i]) - A_num++; - for (j = 0; j < 4; j++) - if (i == j) - continue; - else if (data[i] == answer[j]) { - B_num++; - break; - } - } - if (A_num == 4) - return 1; - move(count + 8, 55); - prints("%s => " ANSI_COLOR(1;32) "%dA %dB" ANSI_RESET, data, A_num, B_num); - return 0; -} - -static int -result(int correct, int number) -{ - char a = 0, b = 0, i, j; - char n1[5], n2[5]; - - snprintf(n1, sizeof(n1), "%04d", correct); - snprintf(n2, sizeof(n2), "%04d", number); - for (i = 0; i < 4; i++) - for (j = 0; j < 4; j++) - if (n1[(int)i] == n2[(int)j]) - b++; - for (i = 0; i < 4; i++) - if (n1[(int)i] == n2[(int)i]) { - b--; - a++; - } - return 10 * a + b; -} - -static int -legal(int number) -{ - char i, j; - char temp[5]; - - snprintf(temp, sizeof(temp), "%04d", number); - for (i = 0; i < 4; i++) - for (j = i + 1; j < 4; j++) - if (temp[(int)i] == temp[(int)j]) - return 0; - return 1; -} - -static void -initcomputer(char flag[]) -{ - int i; - - for (i = 0; i < 10000; i++) - if (legal(i)) - flag[i] = 1; - else - flag[i] = 0; -} - -static int -computer(int correct, int total, char flag[], int n[]) -{ - int guess; - static int j; - int k, i; - char data[5]; - - if (total == 1) { - do { - guess = random() % 10000; - } while (!legal(guess)); - } else - guess = n[random() % j]; - k = result(correct, guess); - if (k == 40) { - move(total + 8, 25); - snprintf(data, sizeof(data), "%04d", guess); - prints("%s => ²q¤¤¤F!!", data); - return 1; - } else { - move(total + 8, 25); - snprintf(data, sizeof(data), "%04d", guess); - prints("%s => " ANSI_COLOR(1;32) "%dA %dB" ANSI_RESET, data, k / 10, k % 10); - } - j = 0; - for (i = 0; i < 10000; i++) - if (flag[i]) { - if (result(i, guess) != k) - flag[i] = 0; - else - n[j++] = i; - } - return 0; -} - -static void -Diff_Random(char *answer) -{ - register int i = 0, j, k; - - while (i < 4) { - k = random() % 10 + '0'; - for (j = 0; j < i; j++) - if (k == answer[j]) - break; - if (j == i) { - answer[j] = k; - i++; - } - } - answer[4] = 0; -} - -#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 - -int -guess_main(void) -{ - char data[5]; - int money; - char computerwin = 0, youwin = 0; - int count = 0, c_count = 0; - char ifcomputer[2]; - char answer[5]; - int *n = NULL; - char yournum[5]; - char *flag = NULL; - char TABLE[] = {0, 10, 8, 4, 2, 1, 0, 0, 0, 0, 0}; - FILE *file; - - clear(); - showtitle("²q¼Æ¦r", BBSName); - lockreturn0(GUESSNUM, LOCK_MULTI); - - reload_money(); - if (cuser.money < 5) { - clear(); - move(12, 35); - unlockutmpmode(); - vmsg("¿ú¤£°÷°Õ ¦Ü¤Ön 5 " MONEYNAME "$"); - return 1; - } - if ((money = get_money()) == 0) - return 1; - vice(money, "²q¼Æ¦r"); - - Diff_Random(answer); - move(2, 0); - clrtoeol(); - prints("±z¤Uª` :%d " MONEYNAME "$", money); - - getdata_str(4, 0, "±zn©M¹q¸£¤ñÁɶÜ? <y/n>[y]:", - ifcomputer, sizeof(ifcomputer), LCECHO, "y"); - if (ifcomputer[0] == 'y') { - ifcomputer[0] = 1; - show_table(TABLE, 1); - } else { - ifcomputer[0] = 0; - show_table(TABLE, 0); - } - if (ifcomputer[0]) { - do { - getdata(5, 0, "½Ð¿é¤J±znÅý¹q¸£²qªº¼Æ¦r: ", - yournum, sizeof(yournum), LCECHO); - } while (!legal(atoi(yournum))); - move(8, 25); - outs("¹q¸£²q"); - flag = malloc(sizeof(char) * 10000); - n = malloc(sizeof(int) * 1500); - initcomputer(flag); - } - move(8, 55); - outs("§A²q"); - while (((!computerwin || !youwin) && count < 10 && (ifcomputer[0])) || - (!ifcomputer[0] && count < 10 && !youwin)) { - if (!computerwin && ifcomputer[0]) { - ++c_count; - if (computer(atoi(yournum), c_count, flag, n)) - computerwin = 1; - } - move(20, 55); - prints("²Ä %d ¦¸¾÷·| ", count + 1); - if (!youwin) { - ++count; - if (guess_play(get_data(data, count), answer, count)) - youwin = 1; - } - } - move(17, 35); - free(flag); - free(n); - if (ifcomputer[0]) { - if (count > c_count) { - outs("§A¿éµ¹¹q¸£¤F"); - move(18, 35); - prints("§A½ß¤F %d ", money); - if ((file = fopen(LOGPASS, "a"))) { - fprintf(file, "¹q¸£²Ä%d¦¸²q¤¤, ", c_count); - if (youwin) - fprintf(file, "%s ²Ä%d¦¸²q¤¤, ", cuser.userid, count); - else - fprintf(file, "%s ¨S²q¤¤, ", cuser.userid); - fprintf(file, "¹q¸£ÁȨ«¤F%s %d " MONEYNAME "$\n", cuser.userid, money); - fclose(file); - } - } else if (count < c_count) { - outs("¯u¼F®`, Åý§AÁȨìÅo"); - move(18, 35); - prints("§AÁȨ«¤F %d ", money * 2); - demoney(money * 2); - if ((file = fopen(LOGPASS, "a"))) { - fprintf(file, "id: %s, ²Ä%d¦¸²q¤¤, ¹q¸£²Ä%d¦¸²q¤¤, " - "ŤF¹q¸£ %d " MONEYNAME "$\n", cuser.userid, count, - c_count, money * 2); - fclose(file); - } - } else { - prints("¯u¼F®`, ©M¹q¸£¥´¦¨¥¤â¤F, ®³¦^¥»¿ú%d\n", money); - demoney(money); - if ((file = fopen(LOGPASS, "a"))) { - fprintf(file, "id: %s ©M¹q¸£¥´¦¨¤F¥¤â\n", cuser.userid); - fclose(file); - } - } - unlockutmpmode(); - pressanykey(); - return 1; - } - if (youwin) { - demoney(TABLE[count] * money); - if (count < 5) { - outs("¯u¼F®`, ¿ú³Q§AÁȨ«¤F"); - if ((file = fopen(LOGPASS, "a"))) { - fprintf(file, "id: %s, ²Ä%d¦¸²q¤¤, ŤF %d " MONEYNAME "$\n", - cuser.userid, count, TABLE[count] * money); - fclose(file); - } - } else if (count > 5) { - outs("ü, ¤Ó¦h¦¸¤~²q¥X¨Ó¤F"); - if ((file = fopen(LOGPASS, "a"))) { - fprintf(file, "id: %s, ²Ä%d¦¸¤~²q¤¤, ½ß¤F %d " MONEYNAME "$\n", - cuser.userid, count, money); - fclose(file); - } - } else { - outs("¤¦¸²q¥X¨Ó, ÁÙ§A¥»¿ú§a"); - move(18, 35); - clrtoeol(); - prints("§A®³¦^¤F%d " MONEYNAME "$\n", money); - if ((file = fopen(LOGPASS, "a"))) { - fprintf(file, "id: %s, ²Ä%d¦¸²q¤¤, ®³¦^¤F¥»¿ú %d " MONEYNAME "$\n", - cuser.userid, count, money); - fclose(file); - } - } - unlockutmpmode(); - pressanykey(); - return 1; - } - move(17, 35); - prints("¼K¼K ¼Ð·Çµª®×¬O %s ", answer); - move(18, 35); - outs("¤U¦¸¦A¨Ó§a"); - if ((file = fopen(BBSHOME "/etc/loseguess.log", "a"))) { - fprintf(file, "id: %s ½ä¤F %d " MONEYNAME "$\n", cuser.userid, money); - fclose(file); - } - unlockutmpmode(); - pressanykey(); - return 1; -} diff --git a/mbbsd/io.c b/mbbsd/io.c deleted file mode 100644 index ae78bbcd..00000000 --- a/mbbsd/io.c +++ /dev/null @@ -1,1050 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -//kcwu: 80x24 ¤@¯ë¨Ï¥ÎªÌ¦W³æ 1.9k, §t header 2.4k -// ¤@¯ë¤å³¹±À¤å¶¬ù 2590 bytes -#define OBUFSIZE 3072 -#define IBUFSIZE 128 - -/* realXbuf is Xbuf+3 because hz convert library requires buf[-2]. */ -#define CVTGAP (3) - -#ifdef DEBUG -#define register -#endif - -static unsigned char real_outbuf[OBUFSIZE + CVTGAP*2] = " ", - real_inbuf [IBUFSIZE + CVTGAP*2] = " "; - -// use defines instead - it is discovered that sometimes the input/output buffer was overflow, -// without knowing why. -// static unsigned char *outbuf = real_outbuf + 3, *inbuf = real_inbuf + 3; -#define inbuf (real_inbuf +CVTGAP) -#define outbuf (real_outbuf+CVTGAP) - -static int obufsize = 0, ibufsize = 0; -static int icurrchar = 0; - -#ifdef DBG_OUTRPT -// output counter -static unsigned long szTotalOutput = 0, szLastOutput = 0; -extern unsigned char fakeEscape; -unsigned char fakeEscape = 0; - -unsigned char fakeEscFilter(unsigned char c) -{ - if (!fakeEscape) return c; - if (c == ESC_CHR) return '*'; - else if (c == '\n') return 'N'; - else if (c == '\r') return 'R'; - else if (c == '\b') return 'B'; - else if (c == '\t') return 'I'; - return c; -} -#endif // DBG_OUTRPT - -/* ----------------------------------------------------- */ -/* convert routines */ -/* ----------------------------------------------------- */ -#ifdef CONVERT - -extern read_write_type write_type; -extern read_write_type read_type; -extern convert_type input_type; - -inline static ssize_t input_wrapper(void *buf, ssize_t count) { - /* input_wrapper is a special case. - * because we may do nothing, - * a if-branch is better than a function-pointer call. - */ - if(input_type) return (*input_type)(buf, count); - else return count; -} - -inline static int read_wrapper(int fd, void *buf, size_t count) { - return (*read_type)(fd, buf, count); -} - -inline static int write_wrapper(int fd, void *buf, size_t count) { - return (*write_type)(fd, buf, count); -} -#endif - -/* ----------------------------------------------------- */ -/* output routines */ -/* ----------------------------------------------------- */ -void -oflush(void) -{ - if (obufsize) { - STATINC(STAT_SYSWRITESOCKET); -#ifdef CONVERT - write_wrapper(1, outbuf, obufsize); -#else - write(1, outbuf, obufsize); -#endif - obufsize = 0; - } - -#ifdef DBG_OUTRPT - // if (0) - { - static char xbuf[128]; - sprintf(xbuf, ESC_STR "[s" ESC_STR "[H" " [%lu/%lu] " ESC_STR "[u", - szLastOutput, szTotalOutput); - write(1, xbuf, strlen(xbuf)); - szLastOutput = 0; - } -#endif // DBG_OUTRPT - - fsync(1); -} - -void -output(const char *s, int len) -{ -#ifdef DBG_OUTRPT - int i = 0; - if (fakeEscape) - for (i = 0; i < obufsize; i++) - outbuf[i] = fakeEscFilter(outbuf[i]); - - szTotalOutput += len; - szLastOutput += len; -#endif // DBG_OUTRPT - - /* Invalid if len >= OBUFSIZE */ - assert(len<OBUFSIZE); - - if (obufsize + len > OBUFSIZE) { - STATINC(STAT_SYSWRITESOCKET); -#ifdef CONVERT - write_wrapper(1, outbuf, obufsize); -#else - write(1, outbuf, obufsize); -#endif - obufsize = 0; - } - memcpy(outbuf + obufsize, s, len); - obufsize += len; -} - -int -ochar(int c) -{ - -#ifdef DBG_OUTRPT - c = fakeEscFilter(c); - szTotalOutput ++; - szLastOutput ++; -#endif // DBG_OUTRPT - - if (obufsize > OBUFSIZE - 1) { - STATINC(STAT_SYSWRITESOCKET); - /* suppose one byte data doesn't need to be converted. */ - write(1, outbuf, obufsize); - obufsize = 0; - } - outbuf[obufsize++] = c; - return 0; -} - -/* ----------------------------------------------------- */ -/* input routines */ -/* ----------------------------------------------------- */ - -static int i_newfd = 0; -static struct timeval i_to, *i_top = NULL; -static int (*flushf) () = NULL; - -void -add_io(int fd, int timeout) -{ - i_newfd = fd; - if (timeout) { - i_to.tv_sec = timeout; - i_to.tv_usec = 16384; /* Ptt: §ï¦¨16384 ÁקK¤£«ö®Éfor loop¦Ycpu - * time 16384 ¬ù¨C¬í64¦¸ */ - i_top = &i_to; - } else - i_top = NULL; -} - -int -num_in_buf(void) -{ - if (ibufsize <= icurrchar) - return 0; - return ibufsize - icurrchar; -} - -int -input_isfull(void) -{ - return ibufsize >= IBUFSIZE; -} - -/* - * dogetch() is not reentrant-safe. SIGUSR[12] might happen at any time, and - * dogetch() might be called again, and then ibufsize/icurrchar/inbuf might - * be inconsistent. We try to not segfault here... - */ - -static int -dogetch(void) -{ - ssize_t len; - static time4_t lastact; - if (ibufsize <= icurrchar) { - - if (flushf) - (*flushf) (); - - refresh(); - - if (i_newfd) { - - struct timeval timeout; - fd_set readfds; - - if (i_top) - timeout = *i_top; /* copy it because select() might - * change it */ - - FD_ZERO(&readfds); - FD_SET(0, &readfds); - FD_SET(i_newfd, &readfds); - - /* jochang: modify first argument of select from FD_SETSIZE */ - /* since we are only waiting input from fd 0 and i_newfd(>0) */ - - STATINC(STAT_SYSSELECT); - while ((len = select(i_newfd + 1, &readfds, NULL, NULL, - i_top ? &timeout : NULL)) < 0) { - if (errno != EINTR) - abort_bbs(0); - /* raise(SIGHUP); */ - } - - if (len == 0){ - syncnow(); - return I_TIMEOUT; - } - - if (i_newfd && FD_ISSET(i_newfd, &readfds)){ - syncnow(); - return I_OTHERDATA; - } - } - -#ifdef NOKILLWATERBALL - if( currutmp && currutmp->msgcount && !reentrant_write_request ) - write_request(1); -#endif - - STATINC(STAT_SYSREADSOCKET); - - do { - len = tty_read(inbuf, IBUFSIZE); - /* tty_read will handle abort_bbs. - * len <= 0: read more */ -#ifdef CONVERT - if(len > 0) - len = input_wrapper(inbuf, len); -#endif -#ifdef DBG_OUTRPT - // if (0) - { - static char xbuf[128]; - sprintf(xbuf, ESC_STR "[s" ESC_STR "[2;1H [%ld] " - ESC_STR "[u", len); - write(1, xbuf, strlen(xbuf)); - fsync(1); - } -#endif // DBG_OUTRPT - - } while (len <= 0); - - ibufsize = len; - icurrchar = 0; - } - - if (currutmp) { - syncnow(); - /* 3 ¬í¤º¶W¹L¨â byte ¤~ºâ active, anti-antiidle. - * ¤£¹L¤è¦VÁäµ¥²Õ¦XÁ䤣¤î 1 byte */ - if (now - lastact < 3) - currutmp->lastact = now; - lastact = now; - } - - // CR LF are treated as one. - if (inbuf[icurrchar] == Ctrl('M')) - { - if (++icurrchar < ibufsize && - inbuf[icurrchar] == Ctrl('J')) - icurrchar ++; - return Ctrl('M'); - } - return (unsigned char)inbuf[icurrchar++]; -} - -#ifdef DEBUG -/* - * These are for terminal keys debug - */ -void -_debug_print_ibuffer() -{ - static int y = 0; - int i = 0; - - move(y % b_lines, 0); - for (i = 0; i < t_columns; i++) - outc(' '); - move(y % b_lines, 0); - prints("%d. Current Buffer: %d/%d, ", y+1, icurrchar, ibufsize); - outs(ANSI_COLOR(1) "[" ANSI_RESET); - for (i = 0; i < ibufsize; i++) - { - int c = (unsigned char)inbuf[i]; - if(c < ' ') - { - prints(ANSI_COLOR(1;33) "0x%02x" ANSI_RESET, c); - } else { - outc(c); - } - } - outs(ANSI_COLOR(1) "]" ANSI_RESET); - y++; - move(y % b_lines, 0); - for (i = 0; i < t_columns; i++) - outc(' '); -} - -int -_debug_check_keyinput() -{ - int dbcsaware = 0; - int flExit = 0; - - clear(); - while(!flExit) - { - int i = 0; - move(b_lines, 0); - for(i=0; i<t_columns; i++) - outc(' '); - move(b_lines, 0); - if(dbcsaware) - { - outs( ANSI_COLOR(7) "´å¼Ð¦b¦¹" ANSI_RESET - " ´ú¸Õ¤¤¤å¼Ò¦¡·|¤£·|¶Ã°eÁä¡C 'q' Â÷¶}, 'd' ¦^^¤å¼Ò¦¡ "); - move(b_lines, 4); - } else { - outs("Waiting for key input. 'q' to exit, 'd' to try dbcs-aware"); - } - refresh(); - wait_input(-1, 0); - switch(dogetch()) - { - case 'd': - dbcsaware = !dbcsaware; - break; - case 'q': - flExit = 1; - break; - } - _debug_print_ibuffer(); - while(num_in_buf() > 0) - dogetch(); - } - return 0; -} - -#endif - -static int water_which_flag = 0; - -int -igetch(void) -{ - register int ch, mode = 0, last = 0; - while (1) { - ch = dogetch(); - - /* for escape codes, check - * http://support.dell.com/support/edocs/systems/pe2650/en/ug/5g387ad0.htm - */ - if (mode == 0 && ch == KEY_ESC) - mode = 1; - else if (mode == 1) { - - /* Escape sequence */ - - if (ch == '[' || ch == 'O') - { mode = 2; last = ch; } -#if 0 - /* some user complained about this since they wanna - * do Esc-N paste in vedit. - * Before anyone to explain what this is for, - * this will be commented. - */ - else if (ch == '1' || ch == '4') /* what is this!? */ - { mode = 3; last = ch; } -#endif - else { - KEY_ESC_arg = ch; - return KEY_ESC; - } - - } - else if (mode == 2) - { - /* ^[ or ^O, - * ordered by frequency */ - - if(ch >= 'A' && ch <= 'D') /* Cursor key */ - { - return KEY_UP + (ch - 'A'); - } - else if (ch >= '1' && ch <= '6') /* Ins Del Home End PgUp PgDn */ - { - mode = 3; last = ch; - continue; - } - else if(ch == 'O') - { - mode = 4; - continue; - } - else if(ch == 'Z') - { - return KEY_STAB; - } - else if (ch == '0') - { - if (dogetch() == 'Z') - return KEY_STAB; - else - return KEY_UNKNOWN; - } - else if (last == 'O') { - /* ^[O ... */ - if (ch >= 'A' && ch <= 'D') - return KEY_UP + (ch - 'A'); - if (ch >= 'P' && ch <= 'S') // vt100 k1-4 - return KEY_F1 + (ch - 'P'); - if (ch >= 'T' && ch <= '[') // putty vt100+ F5-F12 - return KEY_F5 + (ch - 'T'); - if (ch >= 't' && ch <= 'z') // vt100 F5-F11 - return KEY_F5 + (ch - 't'); - if (ch >= 'p' && ch <= 's') // Old (num or fn)kbd 4 keys - return KEY_F1 + (ch - 'p'); - else if (ch == 'a') // DELL spec - return KEY_F12; - } - else return KEY_UNKNOWN; - } - else if (mode == 3) - { - /* ^[[1-6] */ - - /* ~: Ins Del Home End PgUp PgDn */ - if(ch == '~') - { - // vt220 style - if (last >= '1' && last <= '6') - return KEY_HOME + (last - '1'); - // else, unknown. - return KEY_UNKNOWN; - } - else if (last == '1') - { - if (ch >= '1' && ch <= '6') - { - // use num_in_buf() to prevent waiting keys - if (num_in_buf() && dogetch() == '~') /* must be '~' */ - return KEY_F1 + ch - '1'; - } - else if (ch >= '7' && ch <= '9') - { - // use num_in_buf() to prevent waiting keys - if (num_in_buf() && dogetch() == '~') /* must be '~' */ - return KEY_F6 + ch - '7'; - } - return KEY_UNKNOWN; - } - else if (last == '2') - { - if (ch >= '0' && ch <= '4') - { - // use inbuf() to prevent waiting keys - if (num_in_buf() && dogetch() == '~') /* hope you are '~' */ - return KEY_F9 + ch - '0'; - } - return KEY_UNKNOWN; - } - // if fall here, then escape sequence is broken. - return KEY_UNKNOWN; - } - else // here is switch for default keys - switch (ch) { // XXX: indent error -#ifdef DEBUG - case Ctrl('Q'):{ - struct rusage ru; - getrusage(RUSAGE_SELF, &ru); - vmsgf("sbrk: %d KB, idrss: %d KB, isrss: %d KB", - ((int)sbrk(0) - 0x8048000) / 1024, - (int)ru.ru_idrss, (int)ru.ru_isrss); - } - continue; -#endif - case Ctrl('L'): - redrawwin(); - refresh(); - continue; - - case Ctrl('U'): - if (currutmp != NULL && currutmp->mode != EDITING - && currutmp->mode != LUSERS && currutmp->mode) { - - screen_backup_t old_screen; - int oldroll = roll; - int my_newfd; - - scr_dump(&old_screen); - my_newfd = i_newfd; - i_newfd = 0; - - t_users(); - - i_newfd = my_newfd; - roll = oldroll; - scr_restore(&old_screen); - continue; - } - return ch; - case KEY_TAB: - if (WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW)) - if (currutmp != NULL && watermode > 0) { - check_water_init(); - watermode = (watermode + water_which->count) - % water_which->count + 1; - t_display_new(); - continue; - } - return ch; - - case Ctrl('R'): - if (currutmp == NULL) - return (ch); - - if (currutmp->msgs[0].pid && - WATERMODE(WATER_OFO) && wmofo == NOTREPLYING) { - int my_newfd; - screen_backup_t old_screen; - - scr_dump(&old_screen); - - my_newfd = i_newfd; - i_newfd = 0; - my_write2(); - scr_restore(&old_screen); - i_newfd = my_newfd; - continue; - } else if (!WATERMODE(WATER_OFO)) { - check_water_init(); - if (watermode > 0) { - watermode = (watermode + water_which->count) - % water_which->count + 1; - t_display_new(); - continue; - } else if (currutmp->mode == 0 && - (currutmp->chatid[0] == 2 || currutmp->chatid[0] == 3) && - water_which->count != 0 && watermode == 0) { - /* ²Ä¤G¦¸«ö Ctrl-R */ - watermode = 1; - t_display_new(); - continue; - } else if (watermode == -1 && currutmp->msgs[0].pid) { - /* ²Ä¤@¦¸«ö Ctrl-R (¥²¶·¥ý³Q¥á¹L¤ô²y) */ - screen_backup_t old_screen; - int my_newfd; - scr_dump(&old_screen); - - /* ¦pªG¥¿¦btalkªº¸Ü¥ý¤£³B²z¹ï¤è°e¹L¨Óªº«Ê¥] (¤£¥hselect) */ - my_newfd = i_newfd; - i_newfd = 0; - show_call_in(0, 0); - watermode = 0; -#ifndef PLAY_ANGEL - my_write(currutmp->msgs[0].pid, "¤ô²y¥á¹L¥h¡G ", - currutmp->msgs[0].userid, WATERBALL_GENERAL, NULL); -#else - switch (currutmp->msgs[0].msgmode) { - case MSGMODE_TALK: - case MSGMODE_WRITE: - my_write(currutmp->msgs[0].pid, "¤ô²y¥á¹L¥h¡G ", - currutmp->msgs[0].userid, WATERBALL_GENERAL, NULL); - break; - case MSGMODE_FROMANGEL: - my_write(currutmp->msgs[0].pid, "¦A°Ý¥L¤@¦¸¡G ", - currutmp->msgs[0].userid, WATERBALL_ANGEL, NULL); - break; - case MSGMODE_TOANGEL: - my_write(currutmp->msgs[0].pid, "¦^µª¤p¥D¤H¡G ", - currutmp->msgs[0].userid, WATERBALL_ANSWER, NULL); - break; - } -#endif - i_newfd = my_newfd; - - /* ÁÙì¿Ã¹õ */ - scr_restore(&old_screen); - continue; - } - } - return ch; - - case Ctrl('T'): - if (WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW)) { - if (watermode > 0) { - check_water_init(); - if (watermode > 1) - watermode--; - else - watermode = water_which->count; - t_display_new(); - continue; - } - } - return ch; - - case Ctrl('F'): - if (WATERMODE(WATER_NEW)) { - if (watermode > 0) { - check_water_init(); - if (water_which_flag == (int)water_usies) - water_which_flag = 0; - else - water_which_flag = - (water_which_flag + 1) % (int)(water_usies + 1); - if (water_which_flag == 0) - water_which = &water[0]; - else - water_which = swater[water_which_flag - 1]; - watermode = 1; - t_display_new(); - continue; - } - } - return ch; - - case Ctrl('G'): - if (WATERMODE(WATER_NEW)) { - if (watermode > 0) { - check_water_init(); - water_which_flag = (water_which_flag + water_usies) % (water_usies + 1); - if (water_which_flag == 0) - water_which = &water[0]; - else - water_which = swater[water_which_flag - 1]; - watermode = 1; - t_display_new(); - continue; - } - } - return ch; - - // try to do this in getch() level. -#if 0 - case Ctrl('J'): /* Ptt §â \n ®³±¼ */ -#ifdef PLAY_ANGEL - /* Seams some telnet client still send CR LF when changing lines. - CallAngel(); - */ -#endif - continue; -#endif - - default: - return ch; - } - } - // should not reach here. just to make compiler happy. - return 0; -} - -/* - * wait user input anything for f seconds. - * if f < 0, then wait forever. - * Return 1 if anything available. - */ -int -wait_input(float f, int bIgnoreBuf) -{ - int sel = 0; - fd_set readfds; - struct timeval tv, *ptv = &tv; - - if(!bIgnoreBuf && num_in_buf() > 0) - return 1; - - FD_ZERO(&readfds); - FD_SET(0, &readfds); - - if(f > 0) - { - tv.tv_sec = (long) f; - tv.tv_usec = (f - (long)f) * 1000000L; - } else - ptv = NULL; - -#ifdef STATINC - STATINC(STAT_SYSSELECT); -#endif - - do { - if(!bIgnoreBuf && num_in_buf() > 0) - return 1; - sel = select(1, &readfds, NULL, NULL, ptv); - } while (sel < 0 && errno == EINTR); - /* EINTR, interrupted. I don't care! */ - - if(sel == 0) - return 0; - - return 1; -} - -void -drop_input(void) -{ - icurrchar = ibufsize = 0; -} - -int -peek_input(float f, int c) -{ - int i = 0; - assert (c > 0 && c < ' '); // only ^x keys are safe to be detected. - // other keys may fall into escape sequence. - - if (wait_input(f, 1) && (IBUFSIZE > ibufsize)) - { - int len = tty_read(inbuf + ibufsize, IBUFSIZE - ibufsize); -#ifdef CONVERT - if(len > 0) - len = input_wrapper(inbuf+ibufsize, len); -#endif - if (len > 0) - ibufsize += len; - } - for (i = icurrchar; i < ibufsize; i++) - { - if (inbuf[i] == c) - return 1; - } - return 0; -} - - -#ifdef DBCSAWARE - -int getDBCSstatus(unsigned char *s, int pos) -{ - int sts = DBCS_ASCII; - while(pos >= 0) - { - if(sts == DBCS_LEADING) - sts = DBCS_TRAILING; - else if (*s >= 0x80) - { - sts = DBCS_LEADING; - } else { - sts = DBCS_ASCII; - } - s++, pos--; - } - return sts; -} - -#else - -#define dbcs_off (1) - -#endif - -#define MAXLASTCMD 12 -int -oldgetdata(int line, int col, const char *prompt, char *buf, int len, int echo) -{ - register int ch, i; - int clen, lprompt = 0; - int cx = col, cy = line; - static char lastcmd[MAXLASTCMD][80]; - unsigned char occupy_msg = 0; - -#ifdef DBCSAWARE - unsigned int dbcsincomplete = 0; -#endif - - strip_ansi(buf, buf, STRIP_ALL); - if (prompt) - { - lprompt = strlen_noansi(prompt); - cx += lprompt; - } - - if(line == b_lines-msg_occupied) - occupy_msg=1, msg_occupied ++; - - // workaround poor terminal - move_ansi(line, col); - getyx(&line, &col); - clrtoeol(); - - // (line, col) are real starting address - - if (!echo) { - if (prompt) outs(prompt); - len--; - clen = 0; - while ((ch = igetch()) != '\r') { - if (ch == Ctrl('C')) - { - // abort - clen = 0; - if (len > 1) - buf[1] = ch; // workaround for BBS-Lua - break; - } - if (ch == '\177' || ch == Ctrl('H')) { - if (!clen) { - bell(); - continue; - } - clen--; - continue; - } - if (ch>=0x100 || !isprint(ch)) { - bell(); - continue; - } - if (clen >= len) { - bell(); - continue; - } - buf[clen++] = ch; - } - buf[clen] = '\0'; - outc('\n'); - oflush(); - } else { - int cmdpos = 0; - int currchar = 0; - - len--; - buf[len] = '\0'; - clen = currchar = strlen(buf); - - while (1) { - // refresh from prompt - move(line, col); outc(' '); move(line, col); clrtoeol(); - if (prompt) outs(prompt); - - outs(ANSI_COLOR(7)); - outs(buf); - for(i=clen; i<=len; i++) - outc(' '); - outs(ANSI_RESET); - move(cy, cx + currchar); - - if ((ch = igetch()) == '\r') - break; - - if (ch == Ctrl('C')) - { - // abort - clen = currchar = 0; - if (len > 1) - buf[1] = ch; // workaround for BBS-Lua - break; - } - - switch (ch) { - case Ctrl('A'): - case KEY_HOME: - currchar = 0; - break; - - case Ctrl('E'): - case KEY_END: - currchar = clen; - break; - - case KEY_UNKNOWN: - break; - - case KEY_LEFT: - if (currchar <= 0) - break; - --currchar; -#ifdef DBCSAWARE - if(currchar > 0 && ISDBCSAWARE() && - getDBCSstatus((unsigned char*)buf, currchar) == DBCS_TRAILING) - currchar --; -#endif - break; - - case KEY_RIGHT: - if (!buf[currchar]) - break; - ++currchar; -#ifdef DBCSAWARE - if(buf[currchar] && ISDBCSAWARE() && - getDBCSstatus((unsigned char*)buf, currchar) == DBCS_TRAILING) - currchar++; -#endif - break; - - case Ctrl('Y'): - currchar = 0; - case Ctrl('K'): - /* we shoud be able to avoid DBCS issues in ^K mode */ - buf[currchar] = '\0'; - clen = currchar; - break; - - case KEY_DOWN: case Ctrl('N'): - case KEY_UP: case Ctrl('P'): - strlcpy(lastcmd[cmdpos], buf, sizeof(lastcmd[0])); - if (ch == KEY_UP || ch == Ctrl('P')) - cmdpos++; - else - cmdpos += MAXLASTCMD - 1; - cmdpos %= MAXLASTCMD; - strlcpy(buf, lastcmd[cmdpos], len+1); - clen = currchar = strlen(buf); - break; - - case '\177': - case Ctrl('H'): - if (!currchar) - break; -#ifdef DBCSAWARE - if (ISDBCSAWARE() && getDBCSstatus((unsigned char*)buf, - currchar-1) == DBCS_TRAILING) - { - memmove(buf+currchar-1, buf+currchar, clen-currchar+1); - currchar--, clen--; - } -#endif - memmove(buf+currchar-1, buf+currchar, clen-currchar+1); - currchar--, clen--; - break; - - case Ctrl('D'): - case KEY_DEL: - if (!buf[currchar]) - break; -#ifdef DBCSAWARE - if (ISDBCSAWARE() && buf[currchar+1] && getDBCSstatus( - (unsigned char*)buf, currchar+1) == DBCS_TRAILING) - { - memmove(buf+currchar, buf+currchar+1, clen-currchar); - clen --; - } -#endif - memmove(buf+currchar, buf+currchar+1, clen-currchar); - clen --; - break; - - default: - if (echo == NUMECHO && !isdigit(ch)) - { - bell(); - break; - } - if (isprint2(ch) && clen < len && cx + clen < scr_cols) { -#ifdef DBCSAWARE - if(ISDBCSAWARE()) - { - /* to prevent single byte input */ - if(dbcsincomplete) - { - dbcsincomplete = 0; - } - else if (ch >= 0x80) - { - dbcsincomplete = 1; - if(clen + 2 > len) - { - /* we can't print this. ignore and eat key. */ - igetch(); - dbcsincomplete = 0; - break; - } - } else { - /* nothing, normal key. */ - } - } -#endif - for (i = clen + 1; i > currchar; i--) - buf[i] = buf[i - 1]; - buf[currchar] = ch; - currchar++; - clen++; - } - break; - } /* end case */ - assert(0<=clen); - } /* end while */ - buf[clen] = '\0'; - - if (clen > 1) { - strlcpy(lastcmd[0], buf, sizeof(lastcmd[0])); - memmove(lastcmd+1, lastcmd, (MAXLASTCMD-1)*sizeof(lastcmd[0])); - } - /* why return here? because some code then outs.*/ - // outc('\n'); - move(line+1, 0); - refresh(); - - assert(0<=currchar && currchar<=clen); - assert(0<=clen && clen<=len); - } - - if ((echo == LCECHO) && isupper((int)buf[0])) - buf[0] = tolower(buf[0]); - - if(occupy_msg) msg_occupied --; - return clen; -} - -/* Ptt */ -int -getdata_buf(int line, int col, const char *prompt, char *buf, int len, int echo) -{ - return oldgetdata(line, col, prompt, buf, len, echo); -} - - -int -getdata_str(int line, int col, const char *prompt, char *buf, int len, int echo, const char *defaultstr) -{ - strlcpy(buf, defaultstr, len); - - return oldgetdata(line, col, prompt, buf, len, echo); -} - -int -getdata(int line, int col, const char *prompt, char *buf, int len, int echo) -{ - buf[0] = 0; - return oldgetdata(line, col, prompt, buf, len, echo); -} - -/* vim:sw=4 - */ diff --git a/mbbsd/kaede.c b/mbbsd/kaede.c deleted file mode 100644 index b3d9c0ae..00000000 --- a/mbbsd/kaede.c +++ /dev/null @@ -1,165 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -// TODO move stuff to libbbs(or util)/string.c, ... -// this file can be removed (or not?) - -char * -Ptt_prints(char *str, size_t size, int mode) -{ - char *strbuf = alloca(size); - int r, w; - for( r = w = 0 ; str[r] != 0 && w < (size - 1) ; ++r ) - if( str[r] != ESC_CHR ) - strbuf[w++] = str[r]; - else{ - if( str[++r] != '*' ){ - if(w+2>=size-1) break; - strbuf[w++] = ESC_CHR; - strbuf[w++] = str[r]; - } - else{ - /* Note, w will increased by copied length after */ - switch( str[++r] ){ - - // secure content - - case 't': // current time - strlcpy(strbuf+w, Cdate(&now), size-w); - w += strlen(strbuf+w); - break; - case 'u': // current online users - w += snprintf(&strbuf[w], size - w, - "%d", SHM->UTMPnumber); - break; - - // insecure content - - case 's': // current user id - strlcpy(strbuf+w, cuser.userid, size-w); - w += strlen(strbuf+w); - break; - case 'n': // current user nickname - strlcpy(strbuf+w, cuser.nickname, size-w); - w += strlen(strbuf+w); - break; - case 'l': // current user logins - w += snprintf(&strbuf[w], size - w, - "%d", cuser.numlogins); - break; - case 'p': // current user posts - w += snprintf(&strbuf[w], size - w, - "%d", cuser.numposts); - break; - - /* It's saver not to send these undefined escape string. - default: - strbuf[w++] = ESC_CHR; - strbuf[w++] = '*'; - strbuf[w++] = str[r]; - */ - } - } - } - strbuf[w] = 0; - strip_ansi(str, strbuf, mode); - return str; -} - -// utility from screen.c -void -outs_n(const char *str, int n) -{ - while (*str && n--) { - outc(*str++); - } -} - -// XXX left-right (for large term) -// TODO someday please add ANSI detection version -void -outslr(const char *left, int leftlen, const char *right, int rightlen) -{ - if (left == NULL) - left = ""; - if (right == NULL) - right = ""; - if(*left && leftlen < 0) - leftlen = strlen(left); - if(*right && rightlen < 0) - rightlen = strlen(right); - // now calculate padding - rightlen = t_columns - leftlen - rightlen; - outs(left); - - // ignore right msg if we need to. - if(rightlen >= 0) - { - while(--rightlen > 0) - outc(' '); - outs(right); - } else { - rightlen = t_columns - leftlen; - while(--rightlen > 0) - outc(' '); - } -} - - -/* Jaky */ -void -out_lines(const char *str, int line) -{ - int y, x; - getyx(&y, &x); - while (*str && line) { - if (*str == '\n') - { - move(++y, 0); - line--; - } else - { - outc(*str); - } - str++; - } -} - -void -outmsg(const char *msg) -{ - move(b_lines - msg_occupied, 0); - clrtoeol(); - outs(msg); -} - -void -outmsglr(const char *msg, int llen, const char *rmsg, int rlen) -{ - move(b_lines - msg_occupied, 0); - clrtoeol(); - outslr(msg, llen, rmsg, rlen); - outs(ANSI_RESET ANSI_CLRTOEND); -} - -void -prints(const char *fmt,...) -{ - va_list args; - char buff[1024]; - - va_start(args, fmt); - vsnprintf(buff, sizeof(buff), fmt, args); - va_end(args); - outs(buff); -} - -void -mouts(int y, int x, const char *str) -{ - move(y, x); - clrtoeol(); - outs(str); -} - -// vim:ts=4 diff --git a/mbbsd/lovepaper.c b/mbbsd/lovepaper.c deleted file mode 100644 index 50c643bb..00000000 --- a/mbbsd/lovepaper.c +++ /dev/null @@ -1,114 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -#define DATA "etc/lovepaper.dat" - -int -x_love(void) -{ - char buf1[200], title[TTLEN + 1]; - char receiver[61], path[STRLEN] = "home/"; - int x, y = 0, tline = 0, poem = 0; - FILE *fp, *fpo; - struct tm *gtime; - fileheader_t mhdr; - - setutmpmode(LOVE); - gtime = localtime4(&now); - snprintf(buf1, sizeof(buf1), "%c/%s/love%d%d", - cuser.userid[0], cuser.userid, gtime->tm_sec, gtime->tm_min); - strcat(path, buf1); - move(1, 0); - clrtobot(); - - outs("\nÅwªï¨Ï¥Î±¡®Ñ²£¥Í¾¹ v0.00 ªO \n"); - outs("¦³¦óÃø¥H±Ò¾¦ªº¸Ü,¥æ¥Ñ¨t²ÎÀ°§A»¡§a.\nª¨ª¨»¡ : Àݱ¡¤£¥Çªk.\n"); - - if (!getdata(7, 0, "¦¬«H¤H¡G", receiver, sizeof(receiver), DOECHO)) - return 0; - if (receiver[0] && !(searchuser(receiver, receiver) && - getdata(8, 0, "¥D ÃD¡G", title, - sizeof(title), DOECHO))) { - move(10, 0); - vmsg("¦¬«H¤H©Î¥DÃD¤£¥¿½T,±¡®ÑµLªk¶Ç»¼"); - return 0; - } - fpo = fopen(path, "w"); - assert(fpo); - fprintf(fpo, "\n"); - if ((fp = fopen(DATA, "r"))) { - while (fgets(buf1, 100, fp)) { - switch (buf1[0]) { - case '#': - break; - case '@': - if (!strncmp(buf1, "@begin", 6) || !strncmp(buf1, "@end", 4)) - tline = 3; - else if (!strncmp(buf1, "@poem", 5)) { - poem = 1; - tline = 1; - fprintf(fpo, "\n\n"); - } else - tline = 2; - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - sscanf(buf1, "%d", &x); - y = (random() % (x - 1)) * tline; - break; - default: - if (!poem) { - if (y > 0) - y = y - 1; - else { - if (tline > 0) { - fputs(buf1, fpo); - tline--; - } - } - } else { - if (buf1[0] == '$') - y--; - else if (y == 0) - fputs(buf1, fpo); - } - } - - } - - fclose(fp); - fclose(fpo); - strlcpy(save_title, title, sizeof(save_title)); - curredit |= EDIT_MAIL; - if (vedit(path, YEA, NULL) == -1) { - curredit &= ~EDIT_MAIL; - unlink(path); - clear(); - outs("\n\n ©ñ±ó±H±¡®Ñ\n"); - pressanykey(); - return -2; - } - curredit &= ~EDIT_MAIL; - sethomepath(buf1, receiver); - stampfile(buf1, &mhdr); - Rename(path, buf1); - strlcpy(mhdr.title, save_title, sizeof(mhdr.title)); - strlcpy(mhdr.owner, cuser.userid, sizeof(mhdr.owner)); - sethomedir(path, receiver); - if (append_record(path, &mhdr, sizeof(mhdr)) == -1) - return -1; - sendalert(receiver, ALERT_NEW_MAIL); - hold_mail(buf1, receiver); - return 1; - } else { - vmsg("¥»¯¸¥Ø«eµL±¡®Ñ¸ê®Æ®w¡A½Ð¦V¯¸ªø¤ÏÀ³¡C"); - } - fclose(fpo); - return 0; -} diff --git a/mbbsd/mail.c b/mbbsd/mail.c deleted file mode 100644 index 38e19619..00000000 --- a/mbbsd/mail.c +++ /dev/null @@ -1,2092 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -static int mailkeep = 0, mailsum = 0; -static int mailsumlimit = 0, mailmaxkeep = 0; -static char currmaildir[32]; -static char msg_cc[] = ANSI_COLOR(32) "[¸s²Õ¦W³æ]" ANSI_RESET "\n"; -static char listfile[] = "list.0"; - -// check only 20 mails (one page) is enough. -// #define NEWMAIL_CHECK_RANGE (1) -// checking only 1 mail works more like brc style. -#define NEWMAIL_CHECK_RANGE (5) - -enum SHOWMAIL_MODES { - SHOWMAIL_NORM = 0, - SHOWMAIL_SUM, - SHOWMAIL_RANGE, -}; -static int showmail_mode = SHOWMAIL_NORM; - -int -setforward(void) -{ - char buf[80], ip[50] = "", yn[4]; - FILE *fp; - int flIdiotSent2Self = 0; - int oidlen = strlen(cuser.userid); - - sethomepath(buf, cuser.userid); - strcat(buf, "/.forward"); - if ((fp = fopen(buf, "r"))) { - fscanf(fp, "%" toSTR(sizeof(ip)) "s", ip); - fclose(fp); - } - getdata_buf(b_lines - 1, 0, "½Ð¿é¤J¦Û°ÊÂà±HªºEmail: ", - ip, sizeof(ip), DOECHO); - - /* anti idiots */ - if (strncasecmp(ip, cuser.userid, oidlen) == 0) - { - int addrlen = strlen(ip); - if( addrlen == oidlen || - (addrlen > oidlen && - strcasecmp(ip + oidlen, str_mail_address) == 0)) - flIdiotSent2Self = 1; - } - - if (ip[0] && ip[0] != ' ' && !flIdiotSent2Self) { - getdata(b_lines, 0, "½T©w¶}±Ò¦Û°ÊÂà«H¥\\¯à?(Y/n)", yn, sizeof(yn), - LCECHO); - if (yn[0] != 'n' && (fp = fopen(buf, "w"))) { - fputs(ip, fp); - fclose(fp); - vmsg("³]©w§¹¦¨!"); - return 0; - } - } - unlink(buf); - if(flIdiotSent2Self) - vmsg("¦Û°ÊÂà±H¬O¤£·|³]©wµ¹¦Û¤vªº¡A·Q¨ú®ø¥ÎªÅ¥Õ´N¥i¥H¤F¡C"); - else - vmsg("¨ú®ø¦Û°ÊÂà«H!"); - return 0; -} - -int -toggle_showmail_mode(void) -{ - showmail_mode ++; - showmail_mode %= SHOWMAIL_RANGE; - return FULLUPDATE; -} - -int -built_mail_index(void) -{ - char genbuf[128]; - - move(b_lines - 4, 0); - outs("¥»¥\\¯à¥u¦b«H½cÀÉ·´·l®É¨Ï¥Î¡A" ANSI_COLOR(1;33) "µLªk" ANSI_RESET "±Ï¦^³Q§R°£ªº«H¥ó¡C\n" - "°£«D±z²M·¡³oÓ¥\\¯àªº§@¥Î¡A§_«h" ANSI_COLOR(1;33) "½Ð¤£n¨Ï¥Î" ANSI_RESET "¡C\n" - "ĵ§i¡G¥ô·Nªº¨Ï¥Î±N¾ÉP" ANSI_COLOR(1;33) "¤£¥i¹w´Áªºµ²ªG" ANSI_RESET "¡I\n"); - getdata(b_lines - 1, 0, - "½T©w««Ø«H½c?(y/N)", genbuf, 3, - LCECHO); - if (genbuf[0] != 'y') - return 0; - - snprintf(genbuf, sizeof(genbuf), - BBSHOME "/bin/buildir " BBSHOME "/home/%c/%s > /dev/null", - cuser.userid[0], cuser.userid); - mouts(b_lines - 1, 0, ANSI_COLOR(1;31) "¤w¸g³B²z§¹²¦!! ½Ñ¦h¤£«K ·q½Ðì½Ì~" ANSI_RESET); - system(genbuf); - pressanykey(); - return 0; -} - -int -sendalert(const char *userid, int alert) -{ - userinfo_t *uentp = NULL; - int n, tuid, i; - - if ((tuid = searchuser(userid, NULL)) == 0) - return -1; - - n = count_logins(tuid, 0); - for (i = 1; i <= n; i++) - if ((uentp = (userinfo_t *) search_ulistn(tuid, i))) - uentp->alerts |= alert; - return 0; -} - -int -mail_muser(userec_t muser, const char *title, const char *filename) -{ - return mail_id(muser.userid, title, filename, cuser.userid); -} - -int -mail_id(const char *id, const char *title, const char *src, const char *owner) -{ - fileheader_t mhdr; - char dst[128], dirf[128]; - sethomepath(dst, id); - if (stampfile(dst, &mhdr)) - return 0; - strlcpy(mhdr.owner, owner, sizeof(mhdr.owner)); - strlcpy(mhdr.title, title, sizeof(mhdr.title)); - mhdr.filemode = 0; - Copy(src, dst); - - sethomedir(dirf, id); - append_record_forward(dirf, &mhdr, sizeof(mhdr), id); - sendalert(id, ALERT_NEW_MAIL); - return 0; -} - -int -invalidaddr(const char *addr) -{ -#ifdef DEBUG_FWDADDRERR - const char *origaddr = addr; - char errmsg[PATHLEN]; -#endif - - if (*addr == '\0') - return 1; /* blank */ - - while (*addr) { -#ifdef DEBUG_FWDADDRERR - if (not_alnum(*addr) && !strchr("[].@-_+", *addr)) - { - int c = (*addr) & 0xff; - clear(); - move(2,0); - outs( - "±z¿é¤Jªº¦ì§}¿ù»~ (address error)¡C \n\n" - "¥Ñ©ó³Ìªñ³\\¦h¤H¤ÏÀ³¥´¤J¥¿½Tªº¦ì§}(id©Îemail)«á¨t²Î·|§PÂ_¿ù»~\n" - "¦ýÀˬd¤£¥Xì¦]¡A©Ò¥H§ÚÌ»Ýn¥¿½Tªº¿ù»~¦^³ø¡C\n\n" - "¦pªG§A½T¹ê¥´¿ù¤F¡A½Ðª½±µ²¤¹L¤U±ªº»¡©ú¡C\n" - "¦pªG§A»{¬°§A¿é¤Jªº¦ì§}½T¹ê¬O¹ïªº¡A½Ð§â¤U±ªº°T®§½Æ»s°_¨Ó\n" - "¨Ã¶K¨ì " GLOBAL_BUGREPORT " ªO¡C¥»¯¸¬°³y¦¨¤£«K²`·P©êºp¡C\n\n" - ANSI_COLOR(1;33)); - sprintf(errmsg, "ì©l¿é¤J¦ì§}: [%s]\n" - "¿ù»~¦ì¸m: ²Ä %d ¦r¤¸: 0x%02X [ %c ]\n", - origaddr, (int)(addr - origaddr+1), c, c); - outs(errmsg); - outs(ANSI_RESET); - vmsg("½Ð«ö¥ô·NÁäÄ~Äò"); - clear(); - return 1; - } -#else - if (not_alnum(*addr) && !strchr("[].@-_", *addr)) - return 1; -#endif - addr++; - } - return 0; -} - -int -m_internet(void) -{ - char receiver[60]; - char title[STRLEN]; - - getdata(20, 0, "¦¬«H¤H¡G", receiver, sizeof(receiver), DOECHO); - trim(receiver); - if (strchr(receiver, '@') && !invalidaddr(receiver) && - getdata(21, 0, "¥D ÃD¡G", title, sizeof(title), DOECHO)) - do_send(receiver, title); - else { - vmsg("¦¬«H¤H©Î¥DÃD¤£¥¿½T,½Ð«·s¿ï¨ú«ü¥O"); - } - return 0; -} - -void -m_init(void) -{ - sethomedir(currmaildir, cuser.userid); -} - -static void -loadmailusage(void) -{ - mailkeep=get_num_records(currmaildir,sizeof(fileheader_t)); - mailsum =get_sum_records(currmaildir, sizeof(fileheader_t)); -} - -void -setupmailusage(void) -{ // Ptt: get_sum_records is a bad function - int max_keepmail = MAX_KEEPMAIL; -#ifdef PLAY_ANGEL - if (HasUserPerm(PERM_SYSSUPERSUBOP | PERM_ANGEL)) -#else - if (HasUserPerm(PERM_SYSSUPERSUBOP)) -#endif - { - mailsumlimit = 900; - max_keepmail = 700; - } - else if (HasUserPerm(PERM_SYSSUBOP | PERM_ACCTREG | PERM_PRG | - PERM_ACTION | PERM_PAINT)) { - mailsumlimit = 700; - max_keepmail = 500; - } else if (HasUserPerm(PERM_BM)) { - mailsumlimit = 500; - max_keepmail = 300; - } else if (HasUserPerm(PERM_LOGINOK)) - mailsumlimit = 200; - else - mailsumlimit = 50; - mailsumlimit += (cuser.exmailbox + ADD_EXMAILBOX) * 10; - mailmaxkeep = max_keepmail + cuser.exmailbox; - loadmailusage(); -} - -#define MAILBOX_LIM_OK 0 -#define MAILBOX_LIM_KEEP 1 -#define MAILBOX_LIM_SUM 2 -static int -chk_mailbox_limit(void) -{ - if (HasUserPerm(PERM_SYSOP) || HasUserPerm(PERM_MAILLIMIT)) - return MAILBOX_LIM_OK; - - if (!mailkeep) - setupmailusage(); - - if (mailkeep > mailmaxkeep) - return MAILBOX_LIM_KEEP; - if (mailsum > mailsumlimit) - return MAILBOX_LIM_SUM; - return MAILBOX_LIM_OK; -} - -int -chkmailbox(void) -{ - m_init(); - - switch (chk_mailbox_limit()) { - case MAILBOX_LIM_KEEP: - bell(); - bell(); - vmsgf("±z«O¦s«H¥ó¼Æ¥Ø %d ¶W¥X¤W %d, ½Ð¾ã²z", mailkeep, mailmaxkeep); - return mailkeep; - - case MAILBOX_LIM_SUM: - bell(); - bell(); - vmsgf("«H½c®e¶q(¤j¤p,«D¥ó¼Æ) %d ¶W¥X¤W %d, " - "½Ð¬å¹Lªøªº¤ô²y°O¿ý©Î«H¥ó", mailsum, mailsumlimit); - if(showmail_mode != SHOWMAIL_SUM) - { - showmail_mode = SHOWMAIL_SUM; - vmsg("«H½cÅã¥Ü¼Ò¦¡¤w¦Û°Ê§ï¬°Åã¥Ü¤j¤p¡A½ÐºÉ³t¾ã²z"); - } - return mailsum; - - default: - return 0; - } -} - -static void -do_hold_mail(const char *fpath, const char *receiver, const char *holder) -{ - char buf[80], title[128]; - - fileheader_t mymail; - - sethomepath(buf, holder); - stampfile(buf, &mymail); - - mymail.filemode = FILE_READ ; - strlcpy(mymail.owner, "[³Æ.§Ñ.¿ý]", sizeof(mymail.owner)); - if (receiver) { - snprintf(title, sizeof(title), "(%s) %s", receiver, save_title); - strlcpy(mymail.title, title, sizeof(mymail.title)); - } else - strlcpy(mymail.title, save_title, sizeof(mymail.title)); - - sethomedir(title, holder); - - unlink(buf); - Copy(fpath, buf); - append_record_forward(title, &mymail, sizeof(mymail), holder); -} - -void -hold_mail(const char *fpath, const char *receiver) -{ - char buf[4]; - - getdata(b_lines - 1, 0, - (cuser.uflag & DEFBACKUP_FLAG) ? - "¤w¶¶§Q±H¥X¡A¬O§_¦Û¦s©³½Z(Y/N)¡H[Y] " : - "¤w¶¶§Q±H¥X¡A¬O§_¦Û¦s©³½Z(Y/N)¡H[N] ", - buf, sizeof(buf), LCECHO); - - if (TOBACKUP(buf[0])) - do_hold_mail(fpath, receiver, cuser.userid); -} - -int -do_send(const char *userid, const char *title) -{ - fileheader_t mhdr; - char fpath[STRLEN]; - char receiver[IDLEN + 1]; - char genbuf[200]; - int internet_mail, i; - userec_t xuser; - - STATINC(STAT_DOSEND); - if (strchr(userid, '@')) - internet_mail = 1; - else { - internet_mail = 0; - if (!getuser(userid, &xuser)) - return -1; - if (!(xuser.userlevel & PERM_READMAIL)) - return -3; - - curredit |= EDIT_MAIL; - curredit &= ~EDIT_ITEM; - } - /* process title */ - if (title) - strlcpy(save_title, title, sizeof(save_title)); - else { - char tmp_title[STRLEN-20]; - getdata(2, 0, "¥DÃD¡G", tmp_title, sizeof(tmp_title), DOECHO); - strlcpy(save_title, tmp_title, sizeof(save_title)); - } - - setutmpmode(SMAIL); - - fpath[0] = '\0'; - - if (internet_mail) { - int res, ch; - - if (vedit(fpath, NA, NULL) == -1) { - unlink(fpath); - clear(); - return -2; - } - clear(); - prints("«H¥ó§Y±N±Hµ¹ %s\n¼ÐÃD¬°¡G%s\n½T©wn±H¥X¶Ü? (Y/N) [Y]", - userid, save_title); - ch = igetch(); - switch (ch) { - case 'N': - case 'n': - outs("N\n«H¥ó¤w¨ú®ø"); - res = -2; - break; - default: - outs("Y\n½ÐµyÔ, «H¥ó¶Ç»¼¤¤...\n"); - res = -#ifndef USE_BSMTP - bbs_sendmail(fpath, save_title, userid); -#else - bsmtp(fpath, save_title, userid); -#endif - hold_mail(fpath, userid); - } - unlink(fpath); - return res; - } else { - strlcpy(receiver, userid, sizeof(receiver)); - sethomepath(genbuf, userid); - stampfile(genbuf, &mhdr); - strlcpy(mhdr.owner, cuser.userid, sizeof(mhdr.owner)); - if (vedit(genbuf, YEA, NULL) == -1) { - unlink(genbuf); - clear(); - return -2; - } - /* why not make title here? */ - strlcpy(mhdr.title, save_title, sizeof(mhdr.title)); - clear(); - sethomefile(fpath, userid, FN_OVERRIDES); - i = belong(fpath, cuser.userid); - sethomefile(fpath, userid, FN_REJECT); - - if (i || !belong(fpath, cuser.userid)) {/* Ptt: ¥Îbelong¦³ÂI°Q¹½ */ - sethomedir(fpath, userid); - if (append_record_forward(fpath, &mhdr, sizeof(mhdr), userid) == -1) - return -1; - sendalert(userid,ALERT_NEW_MAIL); - } - hold_mail(genbuf, userid); - return 0; - } -} - -void -my_send(const char *uident) -{ - switch (do_send(uident, NULL)) { - case -1: - outs(err_uid); - break; - case -2: - outs(msg_cancel); - break; - case -3: - prints("¨Ï¥ÎªÌ [%s] µLªk¦¬«H", uident); - break; - } - pressanykey(); -} - -int -m_send(void) -{ - char uident[40]; - - stand_title("¥BÅ¥·ªº¸Ü"); - usercomplete(msg_uid, uident); - showplans(uident); - if (uident[0]) - my_send(uident); - return 0; -} - -/* ¸s²Õ±H«H¡B¦^«H : multi_send, multi_reply */ -static void -multi_list(int *reciper) -{ - char uid[16]; - char genbuf[200]; - - while (1) { - stand_title("¸s²Õ±H«H¦W³æ"); - ShowNameList(3, 0, msg_cc); - move(1, 0); - outs("(I)¤Þ¤J¦n¤Í (O)¤Þ¤J¤W½u³qª¾ (N)¤Þ¤J·s¤å³¹³qª¾ (0-9)¤Þ¤J¨ä¥L¯S§O¦W³æ"); - getdata(2, 0, - "(A)¼W¥[ (D)§R°£ (M)½T»{±H«H¦W³æ (Q)¨ú®ø ¡H[M]", - genbuf, 4, LCECHO); - switch (genbuf[0]) { - case 'a': - while (1) { - move(1, 0); - usercomplete("½Ð¿é¤Jn¼W¥[ªº¥N¸¹(¥u«ö ENTER µ²§ô·s¼W): ", uid); - if (uid[0] == '\0') - break; - - move(2, 0); - clrtoeol(); - - if (!searchuser(uid, uid)) - outs(err_uid); - else if (!InNameList(uid)) { - AddNameList(uid); - (*reciper)++; - } - ShowNameList(3, 0, msg_cc); - } - break; - case 'd': - while (*reciper) { - move(1, 0); - namecomplete("½Ð¿é¤Jn§R°£ªº¥N¸¹(¥u«ö ENTER µ²§ô§R°£): ", uid); - if (uid[0] == '\0') - break; - if (RemoveNameList(uid)) - (*reciper)--; - ShowNameList(3, 0, msg_cc); - } - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - listfile[5] = genbuf[0]; - genbuf[0] = '1'; - case 'i': - setuserfile(genbuf, genbuf[0] == '1' ? listfile : fn_overrides); - ToggleNameList(reciper, genbuf, msg_cc); - break; - case 'o': - setuserfile(genbuf, "alohaed"); - ToggleNameList(reciper, genbuf, msg_cc); - break; - case 'n': - setuserfile(genbuf, "postlist"); - ToggleNameList(reciper, genbuf, msg_cc); - break; - case 'q': - *reciper = 0; - return; - default: - return; - } - } -} - -static void -multi_send(char *title) -{ - FILE *fp; - struct word_t *p = NULL; - fileheader_t mymail; - char fpath[TTLEN], *ptr; - int reciper, listing; - char genbuf[256]; - - CreateNameList(); - listing = reciper = 0; - if (*quote_file) { - AddNameList(quote_user); - reciper = 1; - fp = fopen(quote_file, "r"); - assert(fp); - while (fgets(genbuf, sizeof(genbuf), fp)) { - if (strncmp(genbuf, "¡° ", 3)) { - if (listing) - break; - } else { - if (listing) { - char *strtok_pos; - ptr = genbuf + 3; - for (ptr = strtok_r(ptr, " \n\r", &strtok_pos); - ptr; - ptr = strtok_r(NULL, " \n\r", &strtok_pos)) { - if (searchuser(ptr, ptr) && !InNameList(ptr) && - strcmp(cuser.userid, ptr)) { - AddNameList(ptr); - reciper++; - } - } - } else if (!strncmp(genbuf + 3, "[³q§i]", 6)) - listing = 1; - } - } - fclose(fp); - ShowNameList(3, 0, msg_cc); - } - multi_list(&reciper); - move(1, 0); - clrtobot(); - - if (reciper) { - setutmpmode(SMAIL); - if (title) - do_reply_title(2, title); - else { - getdata(2, 0, "¥DÃD¡G", fpath, sizeof(fpath), DOECHO); - snprintf(save_title, sizeof(save_title), "[³q§i] %s", fpath); - } - - setuserfile(fpath, fn_notes); - - if ((fp = fopen(fpath, "w"))) { - fprintf(fp, "¡° [³q§i] ¦@ %d ¤H¦¬¥ó", reciper); - listing = 80; - - for (p = toplev; p; p = p->next) { - reciper = strlen(p->word) + 1; - if (listing + reciper > 75) { - listing = reciper; - fprintf(fp, "\n¡°"); - } else - listing += reciper; - - fprintf(fp, " %s", p->word); - } - memset(genbuf, '-', 75); - genbuf[75] = '\0'; - fprintf(fp, "\n%s\n\n", genbuf); - fclose(fp); - } - curredit |= EDIT_LIST; - - if (vedit(fpath, YEA, NULL) == -1) { - unlink(fpath); - curredit = 0; - vmsg(msg_cancel); - return; - } - listing = 80; - - for (p = toplev; p; p = p->next) { - reciper = strlen(p->word) + 1; - if (listing + reciper > 75) { - listing = reciper; - outc('\n'); - } else { - listing += reciper; - outc(' '); - } - outs(p->word); - if (searchuser(p->word, p->word) && strcmp(STR_GUEST, p->word)) { - sethomefile(genbuf, p->word, FN_OVERRIDES); - if (!belong(genbuf, cuser.userid)) { // not friend, check if rejected - sethomefile(genbuf, p->word, FN_REJECT); - if (belong(genbuf, cuser.userid)) - continue; - } - sethomepath(genbuf, p->word); - } else - continue; - stampfile(genbuf, &mymail); - unlink(genbuf); - Copy(fpath, genbuf); - - strlcpy(mymail.owner, cuser.userid, sizeof(mymail.owner)); - strlcpy(mymail.title, save_title, sizeof(mymail.title)); - mymail.filemode |= FILE_MULTI; /* multi-send flag */ - sethomedir(genbuf, p->word); - if (append_record_forward(genbuf, &mymail, sizeof(mymail), p->word) == -1) - vmsg(err_uid); - sendalert(p->word, ALERT_NEW_MAIL); - } - hold_mail(fpath, NULL); - unlink(fpath); - curredit = 0; - } else - vmsg(msg_cancel); -} - -static int -multi_reply(int ent, fileheader_t * fhdr, const char *direct) -{ - if (!fhdr || !fhdr->filename[0]) - return DONOTHING; - - if (!(fhdr->filemode & FILE_MULTI)) - return mail_reply(ent, fhdr, direct); - - stand_title("¸s²Õ¦^«H"); - strlcpy(quote_user, fhdr->owner, sizeof(quote_user)); - setuserfile(quote_file, fhdr->filename); - if (!dashf(quote_file)) - { - vmsg("ìÀɮפw®ø¥¢¡C"); - return FULLUPDATE; - } - multi_send(fhdr->title); - quote_user[0]='\0'; - quote_file[0]='\0'; - return FULLUPDATE; -} - -int -mail_list(void) -{ - stand_title("¸s²Õ§@·~"); - multi_send(NULL); - return 0; -} - -int -mail_all(void) -{ - FILE *fp; - fileheader_t mymail; - char fpath[TTLEN]; - char genbuf[200]; - int i, unum; - char *userid; - - stand_title("µ¹©Ò¦³¨Ï¥ÎªÌªº¨t²Î³q§i"); - setutmpmode(SMAIL); - getdata(2, 0, "¥DÃD¡G", fpath, sizeof(fpath), DOECHO); - snprintf(save_title, sizeof(save_title), - "[¨t²Î³q§i]" ANSI_COLOR(1;32) " %s" ANSI_RESET, fpath); - - setuserfile(fpath, fn_notes); - - if ((fp = fopen(fpath, "w"))) { - fprintf(fp, "¡° [" ANSI_COLOR(1) "¨t²Î³q§i" ANSI_RESET "] ³o¬O«Êµ¹©Ò¦³¨Ï¥ÎªÌªº«H\n"); - fprintf(fp, "-----------------------------------------------------" - "----------------------\n"); - fclose(fp); - } - *quote_file = 0; - - curredit |= EDIT_MAIL; - curredit &= ~EDIT_ITEM; - if (vedit(fpath, YEA, NULL) == -1) { - curredit = 0; - unlink(fpath); - outs(msg_cancel); - pressanykey(); - return 0; - } - curredit = 0; - - setutmpmode(MAILALL); - stand_title("±H«H¤¤..."); - - sethomepath(genbuf, cuser.userid); - stampfile(genbuf, &mymail); - unlink(genbuf); - Copy(fpath, genbuf); - unlink(fpath); - strcpy(fpath, genbuf); - - strlcpy(mymail.owner, cuser.userid, sizeof(mymail.owner)); /* ¯¸ªø ID */ - strlcpy(mymail.title, save_title, sizeof(mymail.title)); - - sethomedir(genbuf, cuser.userid); - if (append_record_forward(genbuf, &mymail, sizeof(mymail), cuser.userid) == -1) - outs(err_uid); - - for (unum = SHM->number, i = 0; i < unum; i++) { - if (bad_user_id(SHM->userid[i])) - continue; /* Ptt */ - - userid = SHM->userid[i]; - if (strcmp(userid, STR_GUEST) && strcmp(userid, "new") && - strcmp(userid, cuser.userid)) { - sethomepath(genbuf, userid); - stampfile(genbuf, &mymail); - unlink(genbuf); - Copy(fpath, genbuf); - - strlcpy(mymail.owner, cuser.userid, sizeof(mymail.owner)); - strlcpy(mymail.title, save_title, sizeof(mymail.title)); - /* mymail.filemode |= FILE_MARKED; Ptt ¤½§i§ï¦¨¤£·|mark */ - sethomedir(genbuf, userid); - if (append_record_forward(genbuf, &mymail, sizeof(mymail), userid) == -1) - outs(err_uid); - vmsgf("%*s %5d / %5d", IDLEN + 1, userid, i + 1, unum); - } - } - return 0; -} - -int -mail_mbox(void) -{ - char cmd[100]; - fileheader_t fhdr; - - snprintf(cmd, sizeof(cmd), "/tmp/%s.uu", cuser.userid); - snprintf(fhdr.title, sizeof(fhdr.title), "%s ¨p¤H¸ê®Æ", cuser.userid); - doforward(cmd, &fhdr, 'Z'); - return 0; -} - -static int -m_forward(int ent, fileheader_t * fhdr, const char *direct) -{ - char uid[STRLEN]; - - stand_title("Âà¹F«H¥ó"); - usercomplete(msg_uid, uid); - if (uid[0] == '\0') - return FULLUPDATE; - - strlcpy(quote_user, fhdr->owner, sizeof(quote_user)); - setuserfile(quote_file, fhdr->filename); - snprintf(save_title, sizeof(save_title), "%.64s (fwd)", fhdr->title); - move(1, 0); - clrtobot(); - prints("Âà«Hµ¹: %s\n¼Ð ÃD: %s\n", uid, save_title); - - switch (do_send(uid, save_title)) { - case -1: - outs(err_uid); - break; - case -2: - outs(msg_cancel); - break; - case -3: - prints("¨Ï¥ÎªÌ [%s] µLªk¦¬«H", uid); - break; - } - pressanykey(); - quote_user[0]='\0'; - quote_file[0]='\0'; - if (strcasecmp(uid, cuser.userid) == 0) - return DIRCHANGED; - return FULLUPDATE; -} - -struct ReadNewMailArg { - int idc; - int *delmsgs; - int delcnt; - int mrd; -}; - -static int -read_new_mail(void * voidfptr, void *optarg) -{ - fileheader_t *fptr=(fileheader_t*)voidfptr; - struct ReadNewMailArg *arg=(struct ReadNewMailArg*)optarg; - char done = NA, delete_it; - char fname[PATHLEN]; - char genbuf[4]; - - arg->idc++; - // XXX fptr->filename may be invalid. - if (fptr->filemode || !fptr->filename[0]) - return 0; - clear(); - move(10, 0); - prints("±znŪ¨Ó¦Û[%s]ªº°T®§(%s)¶Ü¡H", fptr->owner, fptr->title); - getdata(11, 0, "½Ð±z½T©w(Y/N/Q)?[Y] ", genbuf, 3, DOECHO); - if (genbuf[0] == 'q') - return QUIT; - if (genbuf[0] == 'n') - return 0; - - setuserfile(fname, fptr->filename); - fptr->filemode |= FILE_READ; - if (substitute_record(currmaildir, fptr, sizeof(*fptr), arg->idc)) - return -1; - - arg->mrd = 1; - delete_it = NA; - while (!done) { - int more_result = more(fname, YEA); - - switch (more_result) { - case RET_DOREPLY: - mail_reply(arg->idc, fptr, currmaildir); - return FULLUPDATE; - case RET_DOREPLYALL: - multi_reply(arg->idc, fptr, currmaildir); - return FULLUPDATE; - case RET_DORECOMMEND: // we don't accept this. - return FULLUPDATE; - case -1: - return READ_SKIP; - case 0: - break; - default: - return more_result; - } - - outmsglr(MSG_MAILER, MSG_MAILER_LEN, "", 0); - - switch (igetch()) { - case 'r': - case 'R': - mail_reply(arg->idc, fptr, currmaildir); - break; - case 'y': - multi_reply(arg->idc, fptr, currmaildir); - break; - case 'x': - m_forward(arg->idc, fptr, currmaildir); - break; - case 'd': - case 'D': - delete_it = YEA; - default: - done = YEA; - } - } - if (delete_it) { - if(arg->delcnt==1000) { - vmsg("¤@¦¸³Ì¦h§R 1000 «Ê«H"); - return 0; - } - clear(); - prints("§R°£«H¥ó¡m%s¡n", fptr->title); - getdata(1, 0, msg_sure_ny, genbuf, 2, LCECHO); - if (genbuf[0] == 'y') { - if(arg->delmsgs==NULL) { - arg->delmsgs=(int*)malloc(sizeof(int)*1000); - if(arg->delmsgs==NULL) { - vmsg("¥¢±Ñ, ½Ð¬¢¯¸ªø"); - return 0; - } - } - unlink(fname); - arg->delmsgs[arg->delcnt++] = arg->idc; - - loadmailusage(); - } - } - clear(); - return 0; -} - -void setmailalert() -{ - if(load_mailalert(cuser.userid)) - currutmp->alerts |= ALERT_NEW_MAIL; - else - currutmp->alerts &= ~ALERT_NEW_MAIL; -} -int -m_new(void) -{ - struct ReadNewMailArg arg; - clear(); - setutmpmode(RMAIL); - memset(&arg, 0, sizeof(arg)); - clear(); - curredit |= EDIT_MAIL; - curredit &= ~EDIT_ITEM; - if (apply_record(currmaildir, read_new_mail, sizeof(fileheader_t), &arg) == -1) { - if(arg.delmsgs) - free(arg.delmsgs); - vmsg("¨S¦³·s«H¥ó¤F"); - return -1; - } - curredit = 0; - setmailalert(); - while (arg.delcnt--) - delete_record(currmaildir, sizeof(fileheader_t), arg.delmsgs[arg.delcnt]); - if(arg.delmsgs) - free(arg.delmsgs); - vmsg(arg.mrd ? "«H¤w¾\\²¦" : "¨S¦³·s«H¥ó¤F"); - return -1; -} - -static void -mailtitle(void) -{ - char buf[STRLEN]; - int msglen = 0; - - showtitle("¶l¥ó¿ï³æ", BBSName); - prints("[¡ö]Â÷¶}[¡ô¡õ]¿ï¾Ü[¡÷]¾\\Ū«H¥ó [X]Âà¿ý¬ÝªO[F]Âà±H¯¸¥~ " - " [O]¯¸¥~«H:%s [h]¨D§U\n" - ANSI_COLOR(7) " ½s¸¹ %s §@ ªÌ «H ¥ó ¼Ð ÃD" - "", - REJECT_OUTTAMAIL ? ANSI_COLOR(31) "Ãö" ANSI_RESET : "¶}", - (showmail_mode == SHOWMAIL_SUM) ? "¤j ¤p":"¤é ´Á"); - - /* 43 columns in length, used later. */ - buf[0] = 0; - - if (mailsumlimit) - { - /* warning: snprintf returns length "if not limited". - * however if this case, they should be the same. */ - - msglen = snprintf(buf, sizeof(buf), - ANSI_COLOR(32) - " (®e¶q:%d/%dk %d/%d½g) ", - mailsum, mailsumlimit, - mailkeep, mailmaxkeep); - msglen -= strlen(ANSI_COLOR(32)); - } - outslr("", 44, buf, msglen); - outs(ANSI_RESET); -} - -static void -maildoent(int num, fileheader_t * ent) -{ - char *title, *mark, *color = NULL, type = ' '; - char datepart[6]; - char isonline = 0; - - if (ent->filemode & FILE_MARKED) - { - type = (ent->filemode & FILE_READ) ? - 'm' : 'M'; - } - else if (ent->filemode & FILE_REPLIED) - { - type = (ent->filemode & FILE_READ) ? - 'r' : 'R'; - } - else - { - type = (ent->filemode & FILE_READ) ? - ' ' : '+'; - } - - if (TagNum && !Tagger(atoi(ent->filename + 2), 0, TAG_NIN)) - type = 'D'; - - title = subject(mark = ent->title); - if (title == mark) { - color = ANSI_COLOR(1;31); - mark = "¡º"; - } else { - color = ANSI_COLOR(1;33); - mark = "R:"; - } - - strlcpy(datepart, ent->date, sizeof(datepart)); - - isonline = query_online(ent->owner); - - switch(showmail_mode) - { - case SHOWMAIL_SUM: - { - /* evaluate size */ - size_t filesz = 0; - char ut = 'k'; - char buf[MAXPATHLEN]; - struct stat st; - - if( !ent->filename[0] ){ - filesz = 0; - } else { - setuserfile(buf, ent->filename); - if (stat(buf, &st) >= 0) { - filesz = st.st_size; - /* find printing unit */ - filesz = (filesz + 1023) / 1024; - if(filesz > 9999){ - filesz = (filesz+512) / 1024; - ut = 'M'; - } - if(filesz > 9999) { - filesz = (filesz+512) / 1024; - ut = 'G'; - } - } - } - sprintf(datepart, "%4lu%c", (unsigned long)filesz, ut); - } - break; - default: - break; - } - - /* print out */ - if (strncmp(currtitle, title, TTLEN) != 0) - { - /* is title. */ - color = ""; - } - - prints("%6d %c %-6s%s%-15.14s%s%s %s%-*.*s%s\n", - num, type, datepart, - isonline ? ANSI_COLOR(1) : "", - ent->owner, - isonline ? ANSI_RESET : "", - mark, color, - t_columns - 34, t_columns - 34, - title, - *color ? ANSI_RESET : ""); -} - - -static int -mail_del(int ent, const fileheader_t * fhdr, const char *direct) -{ - char genbuf[200]; - - if (fhdr->filemode & FILE_MARKED) - return DONOTHING; - - if (currmode & MODE_SELECT) { - vmsg("½Ð¥ý¦^¨ì¥¿±`¼Ò¦¡«á¦A¶i¦æ§R°£..."); - return READ_REDRAW; - } - - if (getans(msg_del_ny) == 'y') { - if (!delete_record(direct, sizeof(*fhdr), ent)) { - setupmailusage(); - setdirpath(genbuf, direct, fhdr->filename); -#ifdef USE_RECYCLE - RcyAddFile(fhdr, 0, genbuf); -#endif // USE_RECYCLE - unlink(genbuf); - loadmailusage(); - return DIRCHANGED; - } - } - return READ_REDRAW; -} - -int b_call_in(int ent, const fileheader_t * fhdr, const char *direct); - -static int -mail_read(int ent, fileheader_t * fhdr, const char *direct) -{ - char buf[PATHLEN]; - char done, delete_it, replied; - - clear(); - setdirpath(buf, direct, fhdr->filename); - strlcpy(currtitle, subject(fhdr->title), sizeof(currtitle)); - done = delete_it = replied = NA; - while (!done) { - int more_result = more(buf, YEA); - - /* whether success or not, update flag. - * or users may bug about "black-hole" mails - * and blinking notification */ - if( !(fhdr->filemode & FILE_READ)) - { - fhdr->filemode |= FILE_READ; - substitute_ref_record(direct, fhdr, ent); - } - switch (more_result) { - case -1: - /* no such file */ - clear(); - vmsg("¦¹«Ê«HµL¤º®e¡C"); - return FULLUPDATE; - case RET_DOREPLY: - mail_reply(ent, fhdr, direct); - return FULLUPDATE; - case RET_DOREPLYALL: - multi_reply(ent, fhdr, direct); - return FULLUPDATE; - case RET_DORECOMMEND: // we don't accept this. - return FULLUPDATE; - case 0: - break; - default: - return more_result; - } - outmsglr(MSG_MAILER, MSG_MAILER_LEN, "", 0); - - switch (igetch()) { - case 'r': - case 'R': - replied = YEA; - mail_reply(ent, fhdr, direct); - break; - case 'y': - multi_reply(ent, fhdr, direct); - break; - case 'x': - m_forward(ent, fhdr, direct); - break; - case 'd': - delete_it = YEA; - default: - done = YEA; - } - } - if (delete_it) - mail_del(ent, fhdr, direct); - else { - fhdr->filemode |= FILE_READ; - substitute_ref_record(direct, fhdr, ent); - } - return FULLUPDATE; -} - -static int -mail_read_all(int ent, fileheader_t * fhdr, const char *direct) -{ - off_t i = 0, num = 0; - int fd = 0; - fileheader_t xfhdr; - - currutmp->alerts &= ~ALERT_NEW_MAIL; - if ((fd = open(currmaildir, O_RDWR)) < 0) - return DONOTHING; - - if ((num = lseek(fd, 0, SEEK_END)) < 0) - num = 0; - num /= sizeof(fileheader_t); - - i = num - NEWMAIL_CHECK_RANGE; - if (i < 0) i = 0; - - if (lseek(fd, i * (off_t)sizeof(fileheader_t), SEEK_SET) < 0) - i = num; - - for (; i < num; i++) - { - if (read(fd, &xfhdr, sizeof(xfhdr)) <= 0) - break; - if (xfhdr.filemode & FILE_READ) - continue; - xfhdr.filemode |= FILE_READ; - if (lseek(fd, i * (off_t)sizeof(fileheader_t), SEEK_SET) < 0) - break; - write(fd, &xfhdr, sizeof(xfhdr)); - } - - close(fd); - return DIRCHANGED; -} - -static int -mail_unread(int ent, fileheader_t * fhdr, const char *direct) -{ - // this function may cause arguments, so please specify - // if you want this to be enabled. -#ifdef USE_USER_MAIL_UNREAD - if (fhdr && fhdr->filemode & FILE_READ) - { - fhdr->filemode &= ~FILE_READ; - substitute_record(direct, fhdr, ent); - return FULLUPDATE; - } -#endif // USE_USER_MAIL_UNREAD - return DONOTHING; -} - -/* in boards/mail ¦^«Hµ¹ì§@ªÌ¡AÂà«H¯¸¥ç¥i */ -int -mail_reply(int ent, fileheader_t * fhdr, const char *direct) -{ - char uid[STRLEN]; - FILE *fp; - char genbuf[512]; - int oent = ent; - - if (!fhdr || !fhdr->filename[0]) - return DONOTHING; - - stand_title("¦^ «H"); - - /* §PÂ_¬O boards ©Î mail */ - if (curredit & EDIT_MAIL) - setuserfile(quote_file, fhdr->filename); - else - setbfile(quote_file, currboard, fhdr->filename); - - /* find the author */ - strlcpy(quote_user, fhdr->owner, sizeof(quote_user)); - if (strchr(quote_user, '.')) { - char *t; - char *strtok_pos; - genbuf[0] = '\0'; - if ((fp = fopen(quote_file, "r"))) { - fgets(genbuf, sizeof(genbuf), fp); - fclose(fp); - } - t = strtok_r(genbuf, str_space, &strtok_pos); - if (t && (strcmp(t, str_author1)==0 || strcmp(t, str_author2)==0) - && (t=strtok_r(NULL, str_space, &strtok_pos)) != NULL) - strlcpy(uid, t, sizeof(uid)); - else { - vmsg("¿ù»~: §ä¤£¨ì§@ªÌ¡C"); - quote_user[0]='\0'; - quote_file[0]='\0'; - return FULLUPDATE; - } - } else - strlcpy(uid, quote_user, sizeof(uid)); - - /* make the title */ - do_reply_title(3, fhdr->title); - prints("\n¦¬«H¤H: %s\n¼Ð ÃD: %s\n", uid, save_title); - - /* edit, then send the mail */ - ent = curredit; - switch (do_send(uid, save_title)) { - case -1: - outs(err_uid); - break; - case -2: - outs(msg_cancel); - break; - case -3: - prints("¨Ï¥ÎªÌ [%s] µLªk¦¬«H", uid); - break; - - case 0: - /* success */ - if ( direct && /* for board, no direct */ - (curredit & EDIT_MAIL) && - !(fhdr->filemode & FILE_REPLIED)) - { - fhdr->filemode |= FILE_REPLIED; - substitute_ref_record(direct, fhdr, oent); - } - break; - } - curredit = ent; - pressanykey(); - quote_user[0]='\0'; - quote_file[0]='\0'; - if (strcasecmp(uid, cuser.userid) == 0) - return DIRCHANGED; - return FULLUPDATE; -} - -static int -mail_edit(int ent, fileheader_t * fhdr, const char *direct) -{ - char genbuf[200]; - - if (!HasUserPerm(PERM_SYSOP)) - return DONOTHING; - - setdirpath(genbuf, direct, fhdr->filename); - vedit(genbuf, NA, NULL); - return FULLUPDATE; -} - -static int -mail_nooutmail(int ent, fileheader_t * fhdr, const char *direct) -{ - cuser.uflag2 ^= REJ_OUTTAMAIL; - passwd_update(usernum, &cuser); - return FULLUPDATE; - -} - -static int -mail_mark(int ent, fileheader_t * fhdr, const char *direct) -{ - fhdr->filemode ^= FILE_MARKED; - - substitute_ref_record(direct, fhdr, ent); - return PART_REDRAW; -} - -/* help for mail reading */ -static const char * const mail_help[] = { - "\0¹q¤l«H½c¾Þ§@»¡©ú", - "\01°ò¥»©R¥O", - "(p/¡ô)(n/¡õ) «e¤@½g/¤U¤@½g¤å³¹", - "(P)(PgUp) «e¤@¶", - "(N)(PgDn) ¤U¤@¶", - "(¼Æ¦rÁä) ¸õ¨ì²Ä ## µ§", - "($) ¸õ¨ì³Ì«á¤@µ§", - "(r)(¡÷) Ū«H", - "(R)/(y) ¦^«H / ¸s²Õ¦^«H", - "\01¶i¶¥©R¥O", - "(TAB) ¤Á´«Åã¥Ü¼Ò¦¡(¥Ø«e¦³¤@¯ë¤ÎÅã¥Ü¤j¤p)", - "(O) Ãö³¬/¶}±Ò ¯¸¥~«H¥óÂà¤J", - "(c)/(z) ¦¹«H¥ó¦¬¤J¨p¤H«H¥ó§¨/¶i¤J¨p¤H«H¥ó§¨", - "(x)/(X) Âà«Hµ¹¨ä¥¦¨Ï¥ÎªÌ/Âà¿ý¤å³¹¨ì¨ä¥L¬ÝªO", - "(F)/(u) ±N«H¶Ç°e¦^±zªº¹q¤l«H½c/¤ô²y¾ã²z±H¦^«H½c", - "(d) ±þ±¼¦¹«H", - "(D) ±þ±¼«ü©w½d³òªº«H", - "(m) ±N«H¼Ð°O¡A¥H¨¾³Q²M°£", - "(^G) ¥ß§Y««Ø«H½c («H½c·´·l®É¥Î)", - "(t) ¼Ð°O±ý§R°£«H¥ó", - "(^D) §R°£¤w¼Ð°O«H¥ó", - NULL -}; - -static int -m_help(void) -{ - show_help(mail_help); - return FULLUPDATE; -} - -static int -mail_cross_post(int ent, fileheader_t * fhdr, const char *direct) -{ - char xboard[20], fname[80], xfpath[80], xtitle[80], inputbuf[10]; - fileheader_t xfile; - FILE *xptr; - int author = 0; - char genbuf[200]; - char genbuf2[4]; - -#if 0 - // °£«D¦³¤H©ú¥Õ¬°¦ón¥ý ChekPostPerm ¨Ã×´_¡A - // §_«h¥ý disable ³o¬q code - ¥Ø«e±`³y¦¨ crash¡C - // - // XXX (will crash sometimes because currborad is not defined yet) - // ³Â·Ð in2 ¨Ó×´_³o¸Ì: ½T»{Âà¿ý¬°¦ón¥ý CheckPostPerm - if (!currboard || currboard[0] == 0) - { - enter_board(DEFAULT_BOARD); - } - assert(0<=ent-1 && ent-1<MAX_BOARD); - - if (!CheckPostPerm()) { - vmsg("¹ï¤£°_¡A±z¥Ø«eµLªkÂà¿ý¤å³¹¡I"); - return FULLUPDATE; - } -#endif - - move(2, 0); - clrtoeol(); - if (postrecord.times > 1) - { - outs(ANSI_COLOR(1;31) - "½Ðª`·N: Y¹L¶q«½ÆÂà¿ý±Nµø¬°¬~ªO¡A¾ÉP³Q¶}»@³æ°±Åv¡C\n" ANSI_RESET - "Y¦³¯S§O»Ý¨D½Ð¬¢¦UªO¥D¡A½Ð¥LÌÀ°§AÂà¤å¡C\n\n"); - } - move(1, 0); - CompleteBoard("Âà¿ý¥»¤å³¹©ó¬ÝªO¡G", xboard); - - if (*xboard == '\0' || !haspostperm(xboard)) - { - vmsg("µLªkÂà¿ý"); - return FULLUPDATE; - } - - /* É¥ÎÅÜ¼Æ */ - ent = StringHash(fhdr->title); - /* ¦P¼Ë title ¤£ºÞ¹ïþÓªO³£ºâ cross post , ©Ò¥H¤£¥ÎÀˬd author */ - - if ((ent != 0 && ent == postrecord.checksum[0])) { - /* Àˬd cross post ¦¸¼Æ */ - if (postrecord.times++ > MAX_CROSSNUM) - anticrosspost(); - } else { - postrecord.times = 0; - postrecord.last_bid = 0; - postrecord.checksum[0] = ent; - } - - ent = getbnum(xboard); - assert(0<=ent-1 && ent-1<MAX_BOARD); - if (!CheckPostRestriction(ent)) - { - vmsg("§A¤£°÷¸ê²`³á¡I (¥i¦b¬ÝªO¤º«ö i ¬d¬Ý¨î)"); - return FULLUPDATE; - } - -#ifdef USE_COOLDOWN - if(check_cooldown(&bcache[ent - 1])) - return READ_REDRAW; -#endif - - ent = 1; - if (HasUserPerm(PERM_SYSOP) || !strcmp(fhdr->owner, cuser.userid)) { - getdata(2, 0, "(1)ì¤åÂà¸ü (2)ÂÂÂà¿ý®æ¦¡¡H[1] ", - genbuf, 3, DOECHO); - if (genbuf[0] != '2') { - ent = 0; - getdata(2, 0, "«O¯dì§@ªÌ¦WºÙ¶Ü?[Y] ", inputbuf, 3, DOECHO); - if (inputbuf[0] != 'n' && inputbuf[0] != 'N') - author = 1; - } - } - if (ent) - snprintf(xtitle, sizeof(xtitle), "[Âà¿ý]%.66s", fhdr->title); - else - strlcpy(xtitle, fhdr->title, sizeof(xtitle)); - - snprintf(genbuf, sizeof(genbuf), "±Ä¥Îì¼ÐÃD¡m%.60s¡n¶Ü?[Y] ", xtitle); - getdata(2, 0, genbuf, genbuf2, sizeof(genbuf2), LCECHO); - if (*genbuf2 == 'n') - if (getdata(2, 0, "¼ÐÃD¡G", genbuf, TTLEN, DOECHO)) - strlcpy(xtitle, genbuf, sizeof(xtitle)); - - getdata(2, 0, "(S)¦sÀÉ (L)¯¸¤º (Q)¨ú®ø¡H[Q] ", genbuf, 3, LCECHO); - if (genbuf[0] == 'l' || genbuf[0] == 's') { - int currmode0 = currmode; - - currmode = 0; - setbpath(xfpath, xboard); - stampfile(xfpath, &xfile); - if (author) - strlcpy(xfile.owner, fhdr->owner, sizeof(xfile.owner)); - else - strlcpy(xfile.owner, cuser.userid, sizeof(xfile.owner)); - strlcpy(xfile.title, xtitle, sizeof(xfile.title)); - if (genbuf[0] == 'l') { - xfile.filemode = FILE_LOCAL; - } - setuserfile(fname, fhdr->filename); - { - const char *save_currboard; - xptr = fopen(xfpath, "w"); - assert(xptr); - - strlcpy(save_title, xfile.title, sizeof(save_title)); - save_currboard = currboard; - currboard = xboard; - write_header(xptr, save_title); - currboard = save_currboard; - - fprintf(xptr, "¡° [¥»¤åÂà¿ý¦Û %s «H½c]\n\n", cuser.userid); - - b_suckinfile(xptr, fname); - addsignature(xptr, 0); - fclose(xptr); - } - - setbdir(fname, xboard); - append_record(fname, &xfile, sizeof(xfile)); - setbtotal(getbnum(xboard)); - - if (!xfile.filemode) - outgo_post(&xfile, xboard, cuser.userid, cuser.nickname); -#ifdef USE_COOLDOWN - if (bcache[getbnum(xboard) - 1].brdattr & BRD_COOLDOWN) - add_cooldowntime(usernum, 5); - add_posttimes(usernum, 1); -#endif - - // cross-post does not add numpost. - outs("Âà¿ý«H¥ó¤£¼W¥[¤å³¹¼Æ¡A·q½Ð¥]²[¡C"); - - vmsg("¤å³¹Âà¿ý§¹¦¨"); - currmode = currmode0; - } - return FULLUPDATE; -} - -int -mail_man(void) -{ - char buf[PATHLEN], buf1[64]; - int mode0 = currutmp->mode; - int stat0 = currstat; - - // TODO if someday we put things in user man...? - sethomeman(buf, cuser.userid); - - // if user already has man directory or permission, - // allow entering mail-man folder. - - if (!dashd(buf) && !HasUserPerm(PERM_MAILLIMIT)) - return DONOTHING; - - snprintf(buf1, sizeof(buf1), "%s ªº«H¥ó§¨", cuser.userid); - a_menu(buf1, buf, HasUserPerm(PERM_MAILLIMIT) ? 1 : 0, 0, NULL); - currutmp->mode = mode0; - currstat = stat0; - return FULLUPDATE; -} - -// XXX BUG mail_cite ¦³¥i¯à·|¸õ¶i a_menu, ¦Ó a_menu ·| check -// currbid¡C ¤@¾ãÓÁV¿|ªºÅÞ¿è¿ù»~... -static int -mail_cite(int ent, fileheader_t * fhdr, const char *direct) -{ - char fpath[PATHLEN]; - char title[TTLEN + 1]; - static char xboard[20] = ""; - char buf[20]; - int bid; - - setuserfile(fpath, fhdr->filename); - strlcpy(title, "¡º ", sizeof(title)); - strlcpy(title + 3, fhdr->title, sizeof(title) - 3); - a_copyitem(fpath, title, 0, 1); - - if (cuser.userlevel >= PERM_BM) { - move(2, 0); - clrtoeol(); - move(3, 0); - clrtoeol(); - move(1, 0); - - CompleteBoard( - HasUserPerm(PERM_MAILLIMIT) ? - "¿é¤J¬ÝªO¦WºÙ (ª½±µEnter¶i¤J¨p¤H«H¥ó§¨)¡G" : - "¿é¤J¬ÝªO¦WºÙ¡G", - buf); - if (*buf) - strlcpy(xboard, buf, sizeof(xboard)); - if (*xboard && ((bid = getbnum(xboard)) > 0)){ /* XXXbid */ - setapath(fpath, xboard); - setutmpmode(ANNOUNCE); - a_menu(xboard, fpath, - HasUserPerm(PERM_ALLBOARD) ? 2 : is_BM_cache(bid) ? 1 : 0, - bid, - NULL); - } else { - mail_man(); - } - return FULLUPDATE; - } else { - mail_man(); - return FULLUPDATE; - } -} - -static int -mail_save(int ent, fileheader_t * fhdr, const char *direct) -{ - char fpath[PATHLEN]; - char title[TTLEN + 1]; - - if (HasUserPerm(PERM_MAILLIMIT)) { - setuserfile(fpath, fhdr->filename); - strlcpy(title, "¡º ", sizeof(title)); - strlcpy(title + 3, fhdr->title, sizeof(title) - 3); - a_copyitem(fpath, title, fhdr->owner, 1); - sethomeman(fpath, cuser.userid); - a_menu(cuser.userid, fpath, 1, 0, NULL); - return FULLUPDATE; - } - return DONOTHING; -} - -#ifdef OUTJOBSPOOL -static int -mail_waterball(int ent, fileheader_t * fhdr, const char *direct) -{ - static char address[60] = "", cmode = 1; - char fname[500], genbuf[200]; - FILE *fp; - - if (!(strstr(fhdr->title, "¼ö½u") && strstr(fhdr->title, "°O¿ý"))) { - vmsg("¥²¶·¬O ¼ö½u°O¿ý ¤~¯à¨Ï¥Î¤ô²y¾ã²zªºò!"); - return 1; - } - - if (!address[0]) - strlcpy(address, cuser.email, sizeof(address)); - - move(b_lines - 8, 0); clrtobot(); - outs(ANSI_COLOR(1;33;45) "¡¹¤ô²y¾ã²zµ{¦¡ " ANSI_RESET "\n" - "¨t²Î±N·|«ö·Ó©M¤£¦P¤H¥áªº¤ô²y¦U¦Û¿W¥ß\n" - "©ó¾ãÂIªº®ÉÔ (¦y®p®É¬q°£¥~) ±N¸ê®Æ¾ã²z¦n±H°eµ¹±z\n\n\n"); - - if (address[0]) { - snprintf(genbuf, sizeof(genbuf), "±H©¹ [%s] ¶Ü[Y/n/q]¡H ", address); - getdata(b_lines - 5, 0, genbuf, fname, 3, LCECHO); - if (fname[0] == 'q') { - outmsg("¨ú®ø³B²z"); - return 1; - } - if (fname[0] == 'n') - address[0] = '\0'; - } - if (!address[0]) { - move(b_lines-4, 0); - prints( "½Ðª`·N¥Ø«e¥u¤ä´©±H©¹¼Ð·Ç e-mail ¦a§}¡C\n" - "Y·Q±H¦^¦¹«H½c½Ð¥Î¿é¤J %s.bbs@" MYHOSTNAME "\n", cuser.userid); - - getdata(b_lines - 5, 0, "½Ð¿é¤J¶l¥ó¦a§}¡G", fname, 60, DOECHO); - if (fname[0] && strchr(fname, '.')) { - strlcpy(address, fname, sizeof(address)); - } else { - vmsg("¦a§}®æ¦¡¤£¥¿½T¡A¨ú®ø³B²z"); - return 1; - } - } - trim(address); - if (invalidaddr(address)) - return -2; - move(b_lines-4, 0); clrtobot(); - - if( strstr(address, ".bbs") && REJECT_OUTTAMAIL ){ - outs("\n±z¥²¶·n¥´¶}±µ¨ü¯¸¥~«H, ¤ô²y¾ã²z¨t²Î¤~¯à±H¤Jµ²ªG\n" - "½Ð³Â·Ð¨ì¡i¶l¥ó¿ï³æ¡j«ö¤j¼g O§ï¦¨±µ¨ü¯¸¥~«H (¦b¥k¤W¨¤)\n" - "¦A«·s°õ¦æ¥»¥\\¯à :)\n"); - vmsg("½Ð¥´¶}¯¸¥~«H, ¦A«·s°õ¦æ¥»¥\\¯à"); - return FULLUPDATE; - } - - //snprintf(fname, sizeof(fname), "%d\n", cmode); - outs("¨t²Î´£¨Ñ¨âºØ¼Ò¦¡: \n" - "¼Ò¦¡ 0: ºë²¼Ò¦¡, ±N¤£§tÃC¦â±±¨î½X, ¤è«K¥H¯Â¤å¦r½s¿è¾¹¾ã²z¦¬ÂÃ\n" - "¼Ò¦¡ 1: µØÄR¼Ò¦¡, ¥]§tÃC¦â±±¨î½Xµ¥, ¤è«K¦b bbs¤Wª½±µ½s¿è¦¬ÂÃ\n"); - getdata(b_lines - 1, 0, "¨Ï¥Î¼Ò¦¡(0/1/Q)? [1]", fname, 3, LCECHO); - if (fname[0] == 'Q' || fname[0] == 'q') { - outmsg("¨ú®ø³B²z"); - return FULLUPDATE; - } - cmode = (fname[0] != '0' && fname[0] != '1') ? 1 : fname[0] - '0'; - - snprintf(fname, sizeof(fname), BBSHOME "/jobspool/water.src.%s-%d", - cuser.userid, (int)now); - snprintf(genbuf, sizeof(genbuf), "cp " BBSHOME "/home/%c/%s/%s %s", - cuser.userid[0], cuser.userid, fhdr->filename, fname); - system(genbuf); - /* dirty code ;x */ - snprintf(fname, sizeof(fname), BBSHOME "/jobspool/water.des.%s-%d", - cuser.userid, (int)now); - fp = fopen(fname, "wt"); - assert(fp); - fprintf(fp, "%s\n%s\n%d\n", cuser.userid, address, cmode); - fclose(fp); - vmsg("³]©w§¹¦¨, ¨t²Î±N¦b¤U¤@Ó¾ãÂI(¦y®p®É¬q°£¥~)±N¸ê®Æ±Hµ¹±z"); - return FULLUPDATE; -} -#endif -static const onekey_t mail_comms[] = { - { 0, NULL }, // Ctrl('A') - { 0, NULL }, // Ctrl('B') - { 0, NULL }, // Ctrl('C') - { 0, NULL }, // Ctrl('D') - { 0, NULL }, // Ctrl('E') - { 0, NULL }, // Ctrl('F') - { 0, built_mail_index }, // Ctrl('G') - { 0, NULL }, // Ctrl('H') - { 0, toggle_showmail_mode }, // Ctrl('I') - { 0, NULL }, // Ctrl('J') - { 0, NULL }, // Ctrl('K') - { 0, NULL }, // Ctrl('L') - { 0, NULL }, // Ctrl('M') - { 0, NULL }, // Ctrl('N') - { 0, NULL }, // Ctrl('O') // DO NOT USE THIS KEY - UNIX not sending - { 0, NULL }, // Ctrl('P') - { 0, NULL }, // Ctrl('Q') - { 0, NULL }, // Ctrl('R') - { 0, NULL }, // Ctrl('S') - { 0, NULL }, // Ctrl('T') - { 0, NULL }, // Ctrl('U') - { 0, NULL }, // Ctrl('V') - { 0, NULL }, // Ctrl('W') - { 0, NULL }, // Ctrl('X') - { 0, NULL }, // Ctrl('Y') - { 0, NULL }, // Ctrl('Z') 26 - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, // 'A' 65 - { 0, NULL }, // 'B' - { 0, NULL }, // 'C' - { 1, del_range }, // 'D' - { 1, mail_edit }, // 'E' - { 0, NULL }, // 'F' - { 0, NULL }, // 'G' - { 0, NULL }, // 'H' - { 0, NULL }, // 'I' - { 0, NULL }, // 'J' - { 0, NULL }, // 'K' - { 0, NULL }, // 'L' - { 0, NULL }, // 'M' - { 0, NULL }, // 'N' - { 1, mail_nooutmail }, // 'O' - { 0, NULL }, // 'P' - { 0, NULL }, // 'Q' - { 1, mail_reply }, // 'R' - { 0, NULL }, // 'S' - { 1, edit_title }, // 'T' - { 0, NULL }, // 'U' - { 1, mail_unread }, // 'V' - { 0, NULL }, // 'W' - { 1, mail_cross_post }, // 'X' - { 0, NULL }, // 'Y' - { 0, NULL }, // 'Z' 90 - { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, - { 0, NULL }, // 'a' 97 - { 0, NULL }, // 'b' - { 1, mail_cite }, // 'c' - { 1, mail_del }, // 'd' - { 0, NULL }, // 'e' - { 0, NULL }, // 'f' - { 0, NULL }, // 'g' - { 0, m_help }, // 'h' - { 0, NULL }, // 'i' - { 0, NULL }, // 'j' - { 0, NULL }, // 'k' - { 0, NULL }, // 'l' - { 1, mail_mark }, // 'm' - { 0, NULL }, // 'n' - { 0, NULL }, // 'o' - { 0, NULL }, // 'p' - { 0, NULL }, // 'q' - { 1, mail_read }, // 'r' - { 1, mail_save }, // 's' - { 0, NULL }, // 't' -#ifdef OUTJOBSPOOL - { 1, mail_waterball }, // 'u' -#else - { 0, NULL }, // 'u' -#endif - { 0, mail_read_all }, // 'v' - { 1, b_call_in }, // 'w' - { 1, m_forward }, // 'x' - { 1, multi_reply }, // 'y' - { 0, mail_man }, // 'z' 122 -}; - -int -m_read(void) -{ - int back_bid; - if (get_num_records(currmaildir, sizeof(fileheader_t))) { - curredit = EDIT_MAIL; - curredit &= ~EDIT_ITEM; - back_bid = currbid; - currbid = 0; - i_read(RMAIL, currmaildir, mailtitle, maildoent, mail_comms, -1); - currbid = back_bid; - curredit = 0; - setmailalert(); - return 0; - } else { - outs("±z¨S¦³¨Ó«H"); - return XEASY; - } -} - -/* ±H¯¸¤º«H */ -static int -send_inner_mail(const char *fpath, const char *title, const char *receiver) -{ - char fname[PATHLEN]; - fileheader_t mymail; - char rightid[IDLEN+1]; - - if (!searchuser(receiver, rightid)) - return -2; - - /* to avoid DDOS of disk */ - sethomedir(fname, rightid); - if (strcmp(rightid, cuser.userid) == 0) { - if (chk_mailbox_limit()) - return -4; - } - - sethomepath(fname, rightid); - stampfile(fname, &mymail); - if (!strcmp(rightid, cuser.userid)) { - /* Using BBSNAME may be too loooooong. */ - strlcpy(mymail.owner, "[¯¸¤º]", sizeof(mymail.owner)); - mymail.filemode = FILE_READ; - } else - strlcpy(mymail.owner, cuser.userid, sizeof(mymail.owner)); - strlcpy(mymail.title, title, sizeof(mymail.title)); - unlink(fname); - Copy(fpath, fname); - sethomedir(fname, rightid); - append_record_forward(fname, &mymail, sizeof(mymail), rightid); - sendalert(receiver, ALERT_NEW_MAIL); - return 0; -} - -#include <netdb.h> -#include <pwd.h> -#include <time.h> - -#ifndef USE_BSMTP -static int -bbs_sendmail(const char *fpath, const char *title, char *receiver) -{ - char *ptr; - char genbuf[256]; - FILE *fin, *fout; - - /* ¤¤³~ÄdºI */ - if ((ptr = strchr(receiver, ';'))) { - *ptr = '\0'; - } - if ((ptr = strstr(receiver, str_mail_address)) || !strchr(receiver, '@')) { - char hacker[20]; - int len; - - if (strchr(receiver, '@')) { - len = ptr - receiver; - memcpy(hacker, receiver, len); - hacker[len] = '\0'; - } else - strlcpy(hacker, receiver, sizeof(hacker)); - return send_inner_mail(fpath, title, hacker); - } - /* Running the sendmail */ - if (fpath == NULL) { - snprintf(genbuf, sizeof(genbuf), - "/usr/sbin/sendmail %s > /dev/null", receiver); - fin = fopen("etc/confirm", "r"); - } else { - snprintf(genbuf, sizeof(genbuf), - "/usr/sbin/sendmail -f %s%s %s > /dev/null", - cuser.userid, str_mail_address, receiver); - fin = fopen(fpath, "r"); - } - if (fin == NULL) - return -1; - fout = popen(genbuf, "w"); - if (fout == NULL) { - fclose(fin); - return -1; - } - - if (fpath) - fprintf(fout, "Reply-To: %s%s\nFrom: %s <%s%s>\n", - cuser.userid, str_mail_address, - cuser.nickname, - cuser.userid, str_mail_address); - fprintf(fout,"To: %s\nSubject: %s\n" - "Mime-Version: 1.0\r\n" - "Content-Type: text/plain; charset=\"big5\"\r\n" - "Content-Transfer-Encoding: 8bit\r\n" - "X-Disclaimer: " BBSNAME "¹ï¥»«H¤º®e®¤¤£t³d¡C\n\n", - receiver, title); - - while (fgets(genbuf, sizeof(genbuf), fin)) { - if (genbuf[0] == '.' && genbuf[1] == '\n') - fputs(". \n", fout); - else - fputs(genbuf, fout); - } - fclose(fin); - fprintf(fout, ".\n"); - pclose(fout); - return 0; -} -#else /* USE_BSMTP */ - -int -bsmtp(const char *fpath, const char *title, const char *rcpt) -{ - char buf[80], *ptr; - time4_t chrono; - MailQueue mqueue; - - /* check if the mail is a inner mail */ - if ((ptr = strstr(rcpt, str_mail_address)) || !strchr(rcpt, '@')) { - char hacker[20]; - int len; - - if (strchr(rcpt, '@')) { - len = ptr - rcpt; - memcpy(hacker, rcpt, len); - hacker[len] = '\0'; - } else - strlcpy(hacker, rcpt, sizeof(hacker)); - return send_inner_mail(fpath, title, hacker); - } - chrono = now; - - /* stamp the queue file */ - strlcpy(buf, "out/", sizeof(buf)); - for (;;) { - snprintf(buf + 4, sizeof(buf) - 4, "M.%d.%d.A", (int)++chrono, getpid()); - if (!dashf(buf)) { - Copy(fpath, buf); - break; - } - } - - fpath = buf; - - /* setup mail queue */ - mqueue.mailtime = chrono; - // XXX (unused) mqueue.method = method; - strlcpy(mqueue.filepath, fpath, sizeof(mqueue.filepath)); - strlcpy(mqueue.subject, title, sizeof(mqueue.subject)); - strlcpy(mqueue.sender, cuser.userid, sizeof(mqueue.sender)); - strlcpy(mqueue.username, cuser.nickname, sizeof(mqueue.username)); - strlcpy(mqueue.rcpt, rcpt, sizeof(mqueue.rcpt)); - - if (append_record("out/" FN_DIR, (fileheader_t *) & mqueue, sizeof(mqueue)) < 0) - return 0; - return chrono; -} -#endif /* USE_BSMTP */ - -int -doforward(const char *direct, const fileheader_t * fh, int mode) -{ - static char address[STRLEN] = ""; - char fname[PATHLEN]; - char genbuf[PATHLEN]; - int return_no; - - if (!address[0] && strcmp(cuser.email, "x") != 0) - strlcpy(address, cuser.email, sizeof(address)); - - if( mode == 'U' ){ - vmsg("±N¶i¦æ uuencode ¡CY±z¤£²M·¡¤°»ò¬O uuencode ½Ð§ï¥Î FÂà±H¡C"); - } - trim(address); - - // if user has address and not the default 'x' (no-email)... - if (address[0]) { - snprintf(genbuf, sizeof(genbuf), - "½T©wÂà±Hµ¹ [%s] ¶Ü(Y/N/Q)¡H[Y] ", address); - getdata(b_lines, 0, genbuf, fname, 3, LCECHO); - - if (fname[0] == 'q') { - outmsg("¨ú®øÂà±H"); - return 1; - } - if (fname[0] == 'n') - address[0] = '\0'; - } - if (!address[0]) { - do { - getdata(b_lines - 1, 0, "½Ð¿é¤JÂà±H¦a§}¡G", fname, 60, DOECHO); - if (fname[0]) { - if (strchr(fname, '.')) - strlcpy(address, fname, sizeof(address)); - else - snprintf(address, sizeof(address), - "%s.bbs@%s", fname, MYHOSTNAME); - } else { - vmsg("¨ú®øÂà±H"); - return 1; - } - } while (mode == 'Z' && strstr(address, MYHOSTNAME)); - } - /* according to our experiment, many users leave blanks */ - trim(address); - if (invalidaddr(address)) - return -2; - - outmsg("¥¿Âà±H½ÐµyÔ..."); - refresh(); - - /* °lÂÜ¨Ï¥ÎªÌ */ - if (HasUserPerm(PERM_LOGUSER)) - log_user("mailforward to %s ",address); - if (mode == 'Z') { - snprintf(fname, sizeof(fname), - TAR_PATH " cfz /tmp/home.%s.tgz home/%c/%s; " - MUTT_PATH " -a /tmp/home.%s.tgz -s 'home.%s.tgz' '%s' </dev/null;" - "rm /tmp/home.%s.tgz", - cuser.userid, cuser.userid[0], cuser.userid, - cuser.userid, cuser.userid, address, cuser.userid); - system(fname); - return 0; - snprintf(fname, sizeof(fname), TAR_PATH " cfz - home/%c/%s | " - "/usr/bin/uuencode %s.tgz > %s", - cuser.userid[0], cuser.userid, cuser.userid, direct); - system(fname); - strlcpy(fname, direct, sizeof(fname)); - } else if (mode == 'U') { - char tmp_buf[128]; - - snprintf(fname, sizeof(fname), "/tmp/bbs.uu%05d", (int)currpid); - snprintf(tmp_buf, sizeof(tmp_buf), - "/usr/bin/uuencode %s/%s uu.%05d > %s", - direct, fh->filename, (int)currpid, fname); - system(tmp_buf); - } else if (mode == 'F') { - char tmp_buf[128]; - - snprintf(fname, sizeof(fname), "/tmp/bbs.f%05d", (int)currpid); - snprintf(tmp_buf, sizeof(tmp_buf), "%s/%s", direct, fh->filename); - Copy(tmp_buf, fname); - } else - return -1; - - return_no = -#ifndef USE_BSMTP - bbs_sendmail(fname, fh->title, address); -#else - bsmtp(fname, fh->title, address); -#endif - unlink(fname); - return (return_no); -} - -int -load_mailalert(const char *userid) -{ - struct stat st; - char maildir[MAXPATHLEN]; - int fd; - register int num; - fileheader_t my_mail; - - sethomedir(maildir, userid); - if (!HasUserPerm(PERM_BASIC)) - return 0; - if (stat(maildir, &st) < 0) - return 0; - num = st.st_size / sizeof(fileheader_t); - if (num <= 0) - return 0; - if (num > NEWMAIL_CHECK_RANGE) - num = NEWMAIL_CHECK_RANGE; - - /* ¬Ý¬Ý¦³¨S¦³«H¥óÁÙ¨SŪ¹L¡H±qÀɧÀ¦^ÀYÀˬd¡A®Ä²v¸û°ª */ - if ((fd = open(maildir, O_RDONLY)) > 0) { - lseek(fd, st.st_size - sizeof(fileheader_t), SEEK_SET); - while (num--) { - read(fd, &my_mail, sizeof(fileheader_t)); - if (!(my_mail.filemode & FILE_READ)) { - close(fd); - return ALERT_NEW_MAIL; - } - lseek(fd, -(off_t) 2 * sizeof(fileheader_t), SEEK_CUR); - } - close(fd); - } - return 0; -} diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c deleted file mode 100644 index 0c561ed1..00000000 --- a/mbbsd/mbbsd.c +++ /dev/null @@ -1,1832 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -#include "banip.h" - -#ifdef __linux__ -# ifdef CRITICAL_MEMORY -# include <malloc.h> -# endif -# ifdef DEBUG -# include <mcheck.h> -# endif -#endif - - -#define SOCKET_QLEN 4 - -static void do_aloha(const char *hello); -static void getremotename(const struct sockaddr_in * from, char *rhost, char *rname); - -#ifdef CONVERT -void big2gb_init(void*); -void gb2big_init(void*); -void big2uni_init(void*); -void uni2big_init(void*); -#endif - -////////////////////////////////////////////////////////////////// -// Site Optimization -// override these macro if you need more optimization, -// based on OS/lib/package... -#ifndef OPTIMIZE_LISTEN_SOCKET -#define OPTIMIZE_LISTEN_SOCKET(sock,sz) -#endif - -#ifndef XAUTH_HOST -#define XAUTH_HOST(x) x -#endif - -#ifndef XAUTH_GETREMOTENAME -#define XAUTH_GETREMOTENAME(x) x -#endif - -#ifndef XAUTH_TRYREMOTENAME -#define XAUTH_TRYREMOTENAME() -#endif - -#if 0 -static jmp_buf byebye; -#endif - -static char remoteusername[40] = "?"; -static unsigned char enter_uflag; -static int use_shell_login_mode = 0; -static int listen_port = 23; - -#ifdef DETECT_CLIENT -Fnv32_t client_code=FNV1_32_INIT; - -void UpdateClientCode(unsigned char c) -{ - FNV1A_CHAR(c, client_code); -} -#endif - -#ifdef USE_RFORK -#define fork() rfork(RFFDG | RFPROC | RFNOWAIT) -#endif - -/* set signal handler, which won't be reset once signal comes */ -static void -signal_restart(int signum, void (*handler) (int)) -{ - struct sigaction act; - act.sa_handler = handler; - memset(&(act.sa_mask), 0, sizeof(sigset_t)); - act.sa_flags = 0; - sigaction(signum, &act, NULL); -} - -static void -start_daemon(void) -{ - int n, fd; - - /* - * More idiot speed-hacking --- the first time conversion makes the C - * library open the files containing the locale definition and time zone. - * If this hasn't happened in the parent process, it happens in the - * children, once per connection --- and it does add up. - */ - time_t dummy = time(NULL); - struct tm *dummy_time = localtime(&dummy); - char buf[32]; - - strftime(buf, sizeof(buf), "%d/%b/%Y:%H:%M:%S", dummy_time); - -#ifndef NO_FORK - if ((n = fork())) { - exit(0); - } -#endif - - /* rocker.011018: it's a good idea to close all unexcept fd!! */ -#ifndef VALGRIND - n = getdtablesize(); - while (n) - close(--n); - - if( ((fd = open("log/stderr", O_WRONLY | O_CREAT | O_APPEND, 0644)) >= 0) && fd != 2 ){ - dup2(fd, 2); - close(fd); - } -#endif - - if(getenv("SSH_CLIENT")) - unsetenv("SSH_CLIENT"); - - /* - * rocker.011018: we don't need to remember original tty, so request a - * new session id - */ - setsid(); - - /* - * rocker.011018: after new session, we should insure the process is - * clean daemon - */ -#ifndef NO_FORK - if ((n = fork())) { - exit(0); - } -#endif -} - -static void -reapchild(int sig) -{ - int state, pid; - - while ((pid = waitpid(-1, &state, WNOHANG | WUNTRACED)) > 0); -} - -void -log_usies(const char *mode, const char *mesg) -{ - now = time(NULL); - if (!mesg) - log_filef(FN_USIES, LOG_CREAT, - "%s %s %-12s Stay:%d (%s)\n", - Cdate(&now), mode, cuser.userid , - (int)(now - login_start_time) / 60, cuser.nickname); - else - log_filef(FN_USIES, LOG_CREAT, - "%s %s %-12s %s\n", - Cdate(&now), mode, cuser.userid, mesg); - - /* °lÂÜ¨Ï¥ÎªÌ */ - if (HasUserPerm(PERM_LOGUSER)) - log_user("logout"); -} - - -static void -setflags(int mask, int value) -{ - if (value) - cuser.uflag |= mask; - else - cuser.uflag &= ~mask; -} - -void -u_exit(const char *mode) -{ - int diff = (time(0) - login_start_time) / 60; - int dirty = currmode & MODE_DIRTY; - - currmode = 0; - - /* close fd 0 & 1 to terminate network */ - close(0); - close(1); - - assert(strncmp(currutmp->userid,cuser.userid, IDLEN)==0); - if(strncmp(currutmp->userid,cuser.userid, IDLEN)!=0) - return; - - reload_money(); - /* - cuser.goodpost = currutmp->goodpost; - cuser.badpost = currutmp->badpost; - cuser.goodsale = currutmp->goodsale; - cuser.badsale = currutmp->badsale; - */ - - auto_backup(); - setflags(PAGER_FLAG, currutmp->pager != PAGER_ON); - setflags(CLOAK_FLAG, currutmp->invisible); - save_brdbuf(); - brc_finalize(); - - cuser.invisible = currutmp->invisible; - cuser.withme = currutmp->withme; - cuser.pager = currutmp->pager; - memcpy(cuser.mind, currutmp->mind, 4); - setutmpbid(0); - - if (!SHM->GV2.e.shutdown) { - if (!(HasUserPerm(PERM_SYSOP) && HasUserPerm(PERM_SYSOPHIDE)) && - !currutmp->invisible) - do_aloha("<<¤U¯¸³qª¾>> -- §Ú¨«Åo¡I"); - } - - - if ((cuser.uflag != enter_uflag) || dirty || diff) { - if (!diff && cuser.numlogins) - cuser.numlogins = --cuser.numlogins; - /* Leeym ¤W¯¸°±¯d®É¶¡¨î¦¡ */ - } - passwd_update(usernum, &cuser); - purge_utmp(currutmp); - log_usies(mode, NULL); -} - -void -abort_bbs(int sig) -{ - /* ignore normal signals */ - Signal(SIGALRM, SIG_IGN); - Signal(SIGUSR1, SIG_IGN); - Signal(SIGUSR2, SIG_IGN); - Signal(SIGHUP, SIG_IGN); - Signal(SIGTERM, SIG_IGN); - Signal(SIGPIPE, SIG_IGN); - if (currmode) - u_exit("ABORTED"); - exit(0); -} - -#ifdef GCC_NORETURN -static void abort_bbs_debug(int sig) GCC_NORETURN; -#endif - -/* NOTE: It's better to use signal-safe functions. Avoid to call - * functions with global/static variable -- data may be corrupted */ -static void -abort_bbs_debug(int sig) -{ - int i; - sigset_t sigset; - - switch(sig) { - case SIGINT: STATINC(STAT_SIGINT); break; - case SIGQUIT: STATINC(STAT_SIGQUIT); break; - case SIGILL: STATINC(STAT_SIGILL); break; - case SIGABRT: STATINC(STAT_SIGABRT); break; - case SIGFPE: STATINC(STAT_SIGFPE); break; - case SIGBUS: STATINC(STAT_SIGBUS); break; - case SIGSEGV: STATINC(STAT_SIGSEGV); break; - case SIGXCPU: STATINC(STAT_SIGXCPU); break; - } - /* ignore normal signals */ - Signal(SIGALRM, SIG_IGN); - Signal(SIGUSR1, SIG_IGN); - Signal(SIGUSR2, SIG_IGN); - Signal(SIGHUP, SIG_IGN); - Signal(SIGTERM, SIG_IGN); - Signal(SIGPIPE, SIG_IGN); - - /* unblock */ - sigemptyset(&sigset); - sigaddset(&sigset, SIGINT); - sigaddset(&sigset, SIGQUIT); - sigaddset(&sigset, SIGILL); - sigaddset(&sigset, SIGABRT); - sigaddset(&sigset, SIGFPE); - sigaddset(&sigset, SIGBUS); - sigaddset(&sigset, SIGSEGV); - sigaddset(&sigset, SIGXCPU); - sigprocmask(SIG_UNBLOCK, &sigset, NULL); - -#define CRASH_MSG ANSI_COLOR(0) \ - "\r\nµ{¦¡²§±`, ¥ß¨èÂ_½u. \r\n" \ - "½Ð¬¢ " GLOBAL_BUGREPORT " ªO¸Ôz°ÝÃDµo¥Í¸g¹L¡C\r\n" - -#define XCPU_MSG ANSI_COLOR(0) \ - "\r\nµ{¦¡¯Ó¥Î¹L¦hpºâ¸ê·½, ¥ß¨èÂ_½u¡C\r\n" \ - "¥i¯à¬O (a)°õ¦æ¤Ó¦h¯Ó¥Î¸ê·½ªº°Ê§@ ©Î (b)µ{¦¡±¼¤JµL½a°j°é. "\ - "½Ð¬¢ " GLOBAL_BUGREPORT " ªO¸Ôz°ÝÃDµo¥Í¸g¹L¡C\r\n" - - if(sig==SIGXCPU) - write(1, XCPU_MSG, sizeof(XCPU_MSG)); - else - write(1, CRASH_MSG, sizeof(CRASH_MSG)); - - /* close all file descriptors (including the network connection) */ - for (i = 0; i < 256; ++i) - close(i); - - /* log */ - /* assume vsnprintf() in log_file() is signal-safe, is it? */ - log_filef("log/crash.log", LOG_CREAT, - "%d %d %d %.12s\n", time4(NULL), getpid(), sig, cuser.userid); - - /* try logout... not a good idea, maybe crash again. now disabled */ - /* - if (currmode) { - currmode = 0; - u_exit("AXXED"); - } - */ - -#ifdef DEBUGSLEEP - -#ifndef VALGRIND - setproctitle("debug me!(%d)(%s,%d)", sig, cuser.userid, currstat); -#endif - /* do this manually to prevent broken stuff */ - /* will broken currutmp cause problems here? hope not... */ - if(currutmp && strncmp(cuser.userid, currutmp->userid, IDLEN) == EQUSTR) - currutmp->mode = DEBUGSLEEPING; - - sleep(DEBUGSLEEP_SECONDS); -#endif - - exit(0); -} - -/* µn¿ý BBS µ{¦¡ */ -static void -mysrand(void) -{ - srandom(time(NULL) + getpid()); /* ®É¶¡¸ò pid ·í rand ªº seed */ -} - -void -talk_request(int sig) -{ - STATINC(STAT_TALKREQUEST); - bell(); - bell(); - if (currutmp->msgcount) { - char timebuf[100]; - - syncnow(); - move(0, 0); - clrtoeol(); - prints(ANSI_COLOR(33;41) "¡¹%s" ANSI_COLOR(34;47) " [%s] %s " ANSI_COLOR(0) "", - SHM->uinfo[currutmp->destuip].userid, my_ctime(&now,timebuf,sizeof(timebuf)), - (currutmp->sig == 2) ? "«n®ø®§¼s¼½¡I(½ÐCtrl-U,l¬d¬Ý¼ö°T°O¿ý)" - : "©I¥s¡B©I¥s¡AÅ¥¨ì½Ð¦^µª"); - refresh(); - } else { - unsigned char mode0 = currutmp->mode; - char c0 = currutmp->chatid[0]; - screen_backup_t old_screen; - - currutmp->mode = 0; - currutmp->chatid[0] = 1; - scr_dump(&old_screen); - talkreply(); - currutmp->mode = mode0; - currutmp->chatid[0] = c0; - scr_restore(&old_screen); - } -} - -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), ANSI_COLOR(1;37;46) "¡¹%s" ANSI_COLOR(37;45) " %s " ANSI_RESET, - currutmp->msgs[which].userid, currutmp->msgs[which].last_call_in); - else -#endif - snprintf(buf, sizeof(buf), ANSI_COLOR(1;33;46) "¡¹%s" ANSI_COLOR(37;45) " %s " ANSI_RESET, - currutmp->msgs[which].userid, currutmp->msgs[which].last_call_in); - outmsg(buf); - - if (save) { - char genbuf[200]; - if (!fp_writelog) { - sethomefile(genbuf, cuser.userid, fn_writelog); - fp_writelog = fopen(genbuf, "a"); - } - if (fp_writelog) { - fprintf(fp_writelog, "%s [%s]\n", buf, Cdatelite(&now)); - } - } -} - -static int -add_history_water(water_t * w, const msgque_t * msg) -{ - memcpy(&w->msg[w->top], msg, sizeof(msgque_t)); - w->top++; - w->top %= WATERMODE(WATER_OFO) ? 5 : MAX_REVIEW; - - if (w->count < MAX_REVIEW) - w->count++; - - return w->count; -} - -static int -add_history(const msgque_t * msg) -{ - int i = 0, j, waterinit = 0; - water_t *tmp; - check_water_init(); - if (WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW)) - 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 -#ifdef PLAY_ANGEL - && swater[i]->msg[0].msgmode == msg->msgmode - /* When throwing waterball to angel directly */ -#endif - ) - break; - if (i == 5) { - waterinit = 1; - i = 4; - memset(swater[4], 0, sizeof(water_t)); - } else if (!swater[i]) { - water_usies = i + 1; - swater[i] = &water[i + 1]; - waterinit = 1; - } - tmp = swater[i]; - - if (waterinit) { - memcpy(swater[i]->userid, msg->userid, sizeof(swater[i]->userid)); - swater[i]->pid = msg->pid; - } - if (!swater[i]->uin) - swater[i]->uin = currutmp; - - for (j = i; j > 0; j--) - swater[j] = swater[j - 1]; - swater[0] = tmp; - add_history_water(swater[0], msg); - } - if (WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW)) { - if (watermode > 0 && - (water_which == swater[0] || water_which == &water[0])) { - if (watermode < water_which->count) - watermode++; - t_display_new(); - } - } - return i; -} - -void -write_request(int sig) -{ - int i, msgcount; - - STATINC(STAT_WRITEREQUEST); -#ifdef NOKILLWATERBALL - if( reentrant_write_request ) /* kill again by shmctl */ - return; - reentrant_write_request = 1; -#endif - syncnow(); - check_water_init(); - if (WATERMODE(WATER_OFO)) { - /* ¦pªG¥Ø«e¥¿¦b¦^¤ô²y¼Ò¦¡ªº¸Ü, ´N¤£¯à¶i¦æ add_history() , - ¦]¬°·|§ï¼g water[], ¦Ó¨Ï¦^¤ô²y¥ØªºÄê±¼, ©Ò¥H¤À¦¨´XºØ±¡ªp¦Ò¼{. - sig != 0ªí¯uªº¦³¤ô²y¶i¨Ó, ¬GÅã¥Ü. - sig == 0ªí¥Ü¨S¦³¤ô²y¶i¨Ó, ¤£¹L¤§«e©|¦³¤ô²yÁÙ¨S¼g¨ì water[]. - */ - static int alreadyshow = 0; - - if( sig ){ /* ¯uªº¦³¤ô²y¶i¨Ó */ - - /* Yì¨Ó¥¿¦b REPLYING , «h§ï¦¨ RECVINREPLYING, - ³o¼Ë¦b¦^¤ô²yµ²§ô«á, ·|¦A©I¥s¤@¦¸ write_request(0) */ - if( wmofo == REPLYING ) - wmofo = RECVINREPLYING; - - /* Åã¥Ü */ - for( ; alreadyshow < currutmp->msgcount && alreadyshow < MAX_MSGS - ; ++alreadyshow ){ - bell(); - show_call_in(1, alreadyshow); - refresh(); - } - } - - /* ¬Ý¬Ý¬O¤£¬On§â currutmp->msg ®³¦^ water[] (by add_history()) - ¶·n¬O¤£¦b¦^¤ô²y¤¤ (NOTREPLYING) */ - if( wmofo == NOTREPLYING && - (msgcount = currutmp->msgcount) > 0 ){ - for( i = 0 ; i < msgcount ; ++i ) - add_history(&currutmp->msgs[i]); - if( (currutmp->msgcount -= msgcount) < 0 ) - currutmp->msgcount = 0; - alreadyshow = 0; - } - } else { - if (currutmp->mode != 0 && - currutmp->pager != PAGER_OFF && - cuser.userlevel != 0 && - currutmp->msgcount != 0 && - currutmp->mode != TALK && - currutmp->mode != EDITING && - currutmp->mode != CHATING && - currutmp->mode != PAGE && - currutmp->mode != IDLE && - currutmp->mode != MAILALL && currutmp->mode != MONITOR) { - char c0 = currutmp->chatid[0]; - int currstat0 = currstat; - unsigned char mode0 = currutmp->mode; - - currutmp->mode = 0; - currutmp->chatid[0] = 2; - currstat = HIT; - -#ifdef NOKILLWATERBALL - currutmp->wbtime = 0; -#endif - if( (msgcount = currutmp->msgcount) > 0 ){ - for( i = 0 ; i < msgcount ; ++i ){ - bell(); - show_call_in(1, 0); - add_history(&currutmp->msgs[0]); - - if( (--currutmp->msgcount) < 0 ) - i = msgcount; /* force to exit for() */ - else if( currutmp->msgcount > 0 ) - memmove(&currutmp->msgs[0], - &currutmp->msgs[1], - sizeof(msgque_t) * currutmp->msgcount); - igetch(); - } - } - - currutmp->chatid[0] = c0; - currutmp->mode = mode0; - currstat = currstat0; - } else { - bell(); - show_call_in(1, 0); - add_history(&currutmp->msgs[0]); - - refresh(); - currutmp->msgcount = 0; - } - } -#ifdef NOKILLWATERBALL - reentrant_write_request = 0; - currutmp->wbtime = 0; /* race */ -#endif -} - -static userinfo_t* -getotherlogin(int num) -{ - userinfo_t *ui; - do { - if (!(ui = (userinfo_t *) search_ulistn(usernum, num))) - return NULL; /* user isn't logged in */ - - /* skip sleeping process, this is slow if lots */ - if(ui->mode == DEBUGSLEEPING) - num++; - else if(ui->pid <= 0) - num++; - else if(kill(ui->pid, 0) < 0) - num++; - else - break; - } while (1); - - return ui; -} - -static void -multi_user_check(void) -{ - register userinfo_t *ui; - char genbuf[3]; - - if (HasUserPerm(PERM_SYSOP)) - return; /* don't check sysops */ - - srandom(getpid()); - // race condition here, sleep may help..? - if (cuser.userlevel) { - usleep(random()%1000000); // 0~1s - ui = getotherlogin(1); - if(ui == NULL) - return; - - getdata(b_lines - 1, 0, "±z·Q§R°£¨ä¥L«½Æªº login ¶Ü¡H[Y/n] ", - genbuf, 3, LCECHO); - - usleep(random()%1000000); - if (genbuf[0] != 'n') { - do { - // scan again, old ui may be invalid - ui = getotherlogin(1); - if(ui==NULL) - return; - if (ui->pid > 0) { - if(kill(ui->pid, SIGHUP)<0) { - perror("kill SIGHUP fail"); - break; - } - log_usies("KICK ", cuser.nickname); - } else { - fprintf(stderr, "id=%s ui->pid=0\n", cuser.userid); - } - usleep(random()%2000000+1000000); // 1~3s - } while(getotherlogin(3) != NULL); - } else { - /* deny login if still have 3 */ - if (getotherlogin(3) != NULL) - abort_bbs(0); /* Goodbye(); */ - } - } else { - /* allow multiple guest user */ - if (search_ulistn(usernum, MAX_GUEST) != NULL) { - vmsg("©êºp¡A¥Ø«e¤w¦³¤Ó¦h guest ¦b¯¸¤W, ½Ð¥Înewµù¥U¡C"); - exit(1); - } - } -} - -/* bad login */ -static char * const str_badlogin = "logins.bad"; - -static void -logattempt(const char *uid, char type) -{ - char fname[40]; - int fd, len; - char genbuf[200]; - - snprintf(genbuf, sizeof(genbuf), "%c%-12s[%s] %s@%s\n", type, uid, - Cdate(&login_start_time), remoteusername, fromhost); - len = strlen(genbuf); - if ((fd = open(str_badlogin, O_WRONLY | O_CREAT | O_APPEND, 0644)) > 0) { - write(fd, genbuf, len); - close(fd); - } - if (type == '-') { - snprintf(genbuf, sizeof(genbuf), - "[%s] %s\n", Cdate(&login_start_time), fromhost); - len = strlen(genbuf); - sethomefile(fname, uid, str_badlogin); - if ((fd = open(fname, O_WRONLY | O_CREAT | O_APPEND, 0644)) > 0) { - write(fd, genbuf, len); - close(fd); - } - } -} - -void mkuserdir(const char *userid) -{ - char genbuf[200]; - sethomepath(genbuf, userid); - // assume it is a dir, so just check if it is exist - if (access(genbuf, F_OK) != 0) - mkdir(genbuf, 0755); -} - -static void -login_query(void) -{ -#ifdef CONVERT - /* uid ¥[¤@¦ì, for gb login */ - char uid[IDLEN + 2], passbuf[PASSLEN]; - int attempts, len; -#else - char uid[IDLEN + 1], passbuf[PASSLEN]; - int attempts; -#endif - resolve_garbage(); - now = time(0); - -#ifdef DEBUG - move(1, 0); - prints("debugging mode\ncurrent pid: %d\n", getpid()); -#else - show_file("etc/Welcome", 1, -1, SHOWFILE_ALLOW_ALL); -#endif - // XXX why output("1", 1); here? - // this output has been here since rev 1... - // output("1", 1); - - attempts = 0; - while (1) { - if (attempts++ >= LOGINATTEMPTS) { - more("etc/goodbye", NA); - pressanykey(); - exit(1); - } - bzero(&cuser, sizeof(cuser)); - -#ifdef DEBUG - move(19, 0); - prints("current pid: %d ", getpid()); -#endif - - if (getdata(20, 0, "½Ð¿é¤J¥N¸¹¡A©Î¥H[guest]°ÑÆ[¡A¥H[new]µù¥U: ", - uid, sizeof(uid), DOECHO) < 1) - { - // got nothing - outs("½Ð«·s¿é¤J¡C\n"); - continue; - } - -#ifdef CONVERT - /* switch to gb mode if uid end with '.' */ - len = strlen(uid); - if (uid[0] && uid[len - 1] == '.') { - set_converting_type(CONV_GB); - uid[len - 1] = 0; - redrawwin(); - } - else if (uid[0] && uid[len - 1] == ',') { - set_converting_type(CONV_UTF8); - uid[len - 1] = 0; - redrawwin(); - } - else if (len >= IDLEN + 1) - uid[IDLEN] = 0; -#endif - - if (strcasecmp(uid, str_new) == 0) { -#ifdef LOGINASNEW - new_register(); - mkuserdir(cuser.userid); - reginit_fav(); - break; -#else - outs("¥»¨t²Î¥Ø«eµLªk¥H new µù¥U, ½Ð¥Î guest ¶i¤J\n"); - continue; -#endif - } else if (!is_validuserid(uid)) { - - outs(err_uid); - - } else if (strcasecmp(uid, STR_GUEST) == 0) { /* guest */ - - if (initcuser(uid)< 1) exit (0) ; - cuser.userlevel = 0; - cuser.uflag = PAGER_FLAG | BRDSORT_FLAG | MOVIE_FLAG; - cuser.uflag2= 0; // we don't need FAVNEW_FLAG or anything else. - -#ifdef GUEST_DEFAULT_DBCS_NOINTRESC - cuser.uflag |= DBCS_NOINTRESC; -#endif - // can we prevent mkuserdir() here? - mkuserdir(cuser.userid); - break; - - } else { - - /* normal user */ - getdata(21, 0, MSG_PASSWD, - passbuf, sizeof(passbuf), NOECHO); - passbuf[8] = '\0'; - - move (22, 0); clrtoeol(); - outs("¥¿¦bÀˬd±K½X..."); - move(22, 0); refresh(); - /* prepare for later */ - clrtoeol(); - - if( initcuser(uid) < 1 || !cuser.userid[0] || - !checkpasswd(cuser.passwd, passbuf) ){ - - if(is_validuserid(cuser.userid)) - logattempt(cuser.userid , '-'); - outs(ERR_PASSWD); - - } else { - - logattempt(cuser.userid, ' '); - outs("±K½X¥¿½T¡I ¶}©lµn¤J¨t²Î..."); - move(22, 0); refresh(); - clrtoeol(); - - if (strcasecmp(str_sysop, cuser.userid) == 0){ -#ifdef NO_SYSOP_ACCOUNT - exit(0); -#else /* ¦Û°Ê¥[¤W¦UÓ¥DnÅv */ - cuser.userlevel = PERM_BASIC | PERM_CHAT | PERM_PAGE | - PERM_POST | PERM_LOGINOK | PERM_MAILLIMIT | - PERM_CLOAK | PERM_SEECLOAK | PERM_XEMPT | - PERM_SYSOPHIDE | PERM_BM | PERM_ACCOUNTS | - PERM_CHATROOM | PERM_BOARD | PERM_SYSOP | PERM_BBSADM; -#endif - } - /* ¦¸Ó¦³ home ¤F, ¤£ª¾¹D¬°¦ó¦³ªº±b¸¹·|¨S¦³, ³Q¬å±¼¤F? */ - mkuserdir(cuser.userid); - break; - } - } - } - multi_user_check(); -#ifdef DETECT_CLIENT - { - int fd = open("log/client_code",O_WRONLY | O_CREAT | O_APPEND, 0644); - if(fd>=0) { - write(fd, &client_code, sizeof(client_code)); - close(fd); - } - } -#endif -} - -void -add_distinct(const char *fname, const char *line) -{ - FILE *fp; - int n = 0; - - if ((fp = fopen(fname, "a+"))) { - char buffer[80]; - char tmpname[100]; - FILE *fptmp; - - strlcpy(tmpname, fname, sizeof(tmpname)); - strcat(tmpname, "_tmp"); - if (!(fptmp = fopen(tmpname, "w"))) { - fclose(fp); - return; - } - rewind(fp); - while (fgets(buffer, 80, fp)) { - char *p = buffer + strlen(buffer) - 1; - - if (p[-1] == '\n' || p[-1] == '\r') - p[-1] = 0; - if (!strcmp(buffer, line)) - break; - sscanf(buffer + strlen(buffer) + 2, "%d", &n); - fprintf(fptmp, "%s%c#%d\n", buffer, 0, n); - } - - if (feof(fp)) - fprintf(fptmp, "%s%c#1\n", line, 0); - else { - sscanf(buffer + strlen(buffer) + 2, "%d", &n); - fprintf(fptmp, "%s%c#%d\n", buffer, 0, n + 1); - while (fgets(buffer, 80, fp)) { - sscanf(buffer + strlen(buffer) + 2, "%d", &n); - fprintf(fptmp, "%s%c#%d\n", buffer, 0, n); - } - } - fclose(fp); - fclose(fptmp); - rename(tmpname, fname); - } -} - -void -del_distinct(const char *fname, const char *line, int casesensitive) -{ - FILE *fp; - int n = 0; - - if ((fp = fopen(fname, "r"))) { - char buffer[80]; - char tmpname[100]; - FILE *fptmp; - - strlcpy(tmpname, fname, sizeof(tmpname)); - strcat(tmpname, "_tmp"); - if (!(fptmp = fopen(tmpname, "w"))) { - fclose(fp); - return; - } - rewind(fp); - while (fgets(buffer, 80, fp)) { - char *p = buffer + strlen(buffer) - 1; - - if (p[-1] == '\n' || p[-1] == '\r') - p[-1] = 0; - if(casesensitive) - { - if (!strcmp(buffer, line)) - break; - } else { - if (!strcasecmp(buffer, line)) - break; - } - sscanf(buffer + strlen(buffer) + 2, "%d", &n); - fprintf(fptmp, "%s%c#%d\n", buffer, 0, n); - } - - if (!feof(fp)) - while (fgets(buffer, 80, fp)) { - sscanf(buffer + strlen(buffer) + 2, "%d", &n); - fprintf(fptmp, "%s%c#%d\n", buffer, 0, n); - } - fclose(fp); - fclose(fptmp); - rename(tmpname, fname); - } -} - -#ifdef WHERE -static int -where(const char *from) -{ - int i; - - for (i = 0; i < SHM->home_num; i++) { - if ((SHM->home_ip[i] & SHM->home_mask[i]) == (ipstr2int(from) & SHM->home_mask[i])) { - return i; - } - } - return 0; -} -#endif - -static void -check_BM(void) -{ - /* XXX: -_- */ - int i; - - cuser.userlevel &= ~PERM_BM; - for( i = 0 ; i < numboards ; ++i ) - if( is_BM_cache(i + 1) ) /* XXXbid */ - return; - //for (i = 0, bhdr = bcache; i < numboards && !is_BM(bhdr->BM); i++, bhdr++); -} - -static void -setup_utmp(int mode) -{ - /* NOTE, ¦b getnewutmpent ¤§«e¤£À³¸Ó¦³¥ô¦ó slow/blocking function */ - userinfo_t uinfo; - memset(&uinfo, 0, sizeof(uinfo)); - uinfo.pid = currpid = getpid(); - uinfo.uid = usernum; - uinfo.mode = currstat = mode; - - uinfo.userlevel = cuser.userlevel; - uinfo.sex = cuser.sex % 8; - uinfo.lastact = time(NULL); - strlcpy(uinfo.userid, cuser.userid, sizeof(uinfo.userid)); - //strlcpy(uinfo.realname, cuser.realname, sizeof(uinfo.realname)); - strlcpy(uinfo.nickname, cuser.nickname, sizeof(uinfo.nickname)); - strip_nonebig5((unsigned char *)uinfo.nickname, sizeof(uinfo.nickname)); - strlcpy(uinfo.from, fromhost, sizeof(uinfo.from)); - uinfo.five_win = cuser.five_win; - uinfo.five_lose = cuser.five_lose; - uinfo.five_tie = cuser.five_tie; - uinfo.chc_win = cuser.chc_win; - uinfo.chc_lose = cuser.chc_lose; - uinfo.chc_tie = cuser.chc_tie; - uinfo.chess_elo_rating = cuser.chess_elo_rating; - uinfo.go_win = cuser.go_win; - uinfo.go_lose = cuser.go_lose; - uinfo.go_tie = cuser.go_tie; - uinfo.invisible = cuser.invisible % 2; - uinfo.pager = cuser.pager % PAGER_MODES; - /* - uinfo.goodpost = cuser.goodpost; - uinfo.badpost = cuser.badpost; - uinfo.goodsale = cuser.goodsale; - uinfo.badsale = cuser.badsale; - */ - if(cuser.withme & (cuser.withme<<1) & (WITHME_ALLFLAG<<1)) - cuser.withme = 0; /* unset all if contradict */ - uinfo.withme = cuser.withme & ~WITHME_ALLFLAG; - memcpy(uinfo.mind, cuser.mind, 4); - strip_nonebig5((unsigned char *)uinfo.mind, 4); -#ifdef WHERE - uinfo.from_alias = where(fromhost); -#endif -#ifndef FAST_LOGIN - setuserfile(buf, "remoteuser"); - - strlcpy(remotebuf, fromhost, sizeof(fromhost)); - strcat(remotebuf, ctime4(&now)); - chomp(remotebuf); - add_distinct(buf, remotebuf); -#endif - if (enter_uflag & CLOAK_FLAG) - uinfo.invisible = YEA; - -#ifdef PLAY_ANGEL - if (REJECT_QUESTION) - uinfo.angel = 1; - uinfo.angel |= ANGEL_STATUS() << 1; -#endif - - getnewutmpent(&uinfo); - currmode = MODE_STARTED; - SHM->UTMPneedsort = 1; - // XXX ¤£¥Î¨C 20 ¤~Àˬd§a - if (!(cuser.numlogins % 20) && cuser.userlevel & PERM_BM) - check_BM(); /* Ptt ¦Û°Ê¨ú¤UÂ÷¾ªO¥DÅv¤O */ - -#ifndef _BBS_UTIL_C_ - /* Very, very slow friend_load. */ - if( strcmp(cuser.userid, STR_GUEST) != 0 ) // guest ¤£³B²z¦n¤Í - friend_load(0); - nice(3); -#endif -} - -inline static void welcome_msg(void) -{ - prints(ANSI_RESET " Åwªï±z²Ä " - ANSI_COLOR(1;33) "%d" ANSI_COLOR(0;37) " «×«ô³X¥»¯¸¡A¤W¦¸±z¬O±q " - ANSI_COLOR(1;33) "%s" ANSI_COLOR(0;37) " ³s©¹¥»¯¸¡A" - ANSI_CLRTOEND "\n" - " §Ú°O±o¨º¤Ñ¬O " ANSI_COLOR(1;33) "%s" ANSI_COLOR(0;37) "¡C" - ANSI_CLRTOEND "\n" - ANSI_CLRTOEND "\n" - , - ++cuser.numlogins, cuser.lasthost, Cdate(&(cuser.lastlogin))); - pressanykey(); -} - -inline static void check_bad_login(void) -{ - char genbuf[200]; - setuserfile(genbuf, str_badlogin); - if (more(genbuf, NA) != -1) { - move(b_lines - 3, 0); - outs("³q±`¨Ã¨S¦³¿ìªkª¾¹D¸Óip¬O½Ö©Ò¦³, " - "¥H¤Î¨ä·N¹Ï(¬O¤£¤p¤ß«ö¿ù©Î¦³·N´ú±z±K½X)\n" - "Y±z¦³±b¸¹³Qµs¥ÎºÃ¼{, ½Ð¸g±`§ó§ï±zªº±K½X©Î¨Ï¥Î¥[±K³s½u"); - if (getans("±zn§R°£¥H¤W¿ù»~¹Á¸Õªº°O¿ý¶Ü? [y/N] ") == 'y') - unlink(genbuf); - } -} - -inline static void birthday_make_a_wish(const struct tm *ptime, const struct tm *tmp) -{ - if (tmp->tm_mday != ptime->tm_mday) { - more("etc/birth.post", YEA); - if (enter_board("WhoAmI")==0) { - do_post(); - } - } -} - -inline static void record_lasthost(const char *fromhost) -{ - strlcpy(cuser.lasthost, fromhost, sizeof(cuser.lasthost)); -} - -inline static void check_mailbox_quota(void) -{ - if (chkmailbox()) - m_read(); -} - -static void init_guest_info(void) -{ - int i; - char *nick[13] = { - "·¦¤l", "¨©´ß", "¤º¦ç", "Ä_¯S²~", "½¨®³½", - "¾ð¸", "¯BµÓ", "¾c¤l", "¼ç¤ô¸¥", "Å]¤ý", - "ÅKÅø", "¦Ò¨÷", "¤j¬ü¤k" - }; - char *name[13] = { - "¤j¤ý·¦¤l", "ÆxÄMÁ³", "¤ñ°ò¥§", "¥i¤f¥i¼Ö", "¥õªaªº³½", - "¾Ð", "°ª©£«Î", "AIR Jordon", "¬õ¦â¤Q¤ë¸¹", "§å½ð½ð", - "SASAYA·¦¥¤", "Àn³J", "¥¬¾|§J÷«³½»µ·" - }; - char *addr[13] = { - "¤Ñ°ó¼Ö¶é", "¤j®ü", "ºñ®q¤p©]¦±", "¬ü°ê", "ºñ¦â¬À·äÁG", - "»·¤è", "쥻®ü", "NIKE", "ĬÁp", "¨k¤K618«Ç", - "·R¤§¨ý", "¤Ñ¤W", "ÂŦâ¬À·äÁG" - }; - i = login_start_time % 13; - snprintf(cuser.nickname, sizeof(cuser.nickname), - "®üÃäº}¨Óªº%s", nick[(int)i]); - strlcpy(currutmp->nickname, cuser.nickname, - sizeof(currutmp->nickname)); - strlcpy(cuser.realname, name[(int)i], sizeof(cuser.realname)); - strlcpy(cuser.address, addr[(int)i], sizeof(cuser.address)); - cuser.sex = i % 8; - currutmp->pager = PAGER_DISABLE; -} - -#if FOREIGN_REG_DAY > 0 -inline static void foreign_warning(void){ - if ((cuser.uflag2 & FOREIGN) && !(cuser.uflag2 & LIVERIGHT)){ - if (login_start_time - cuser.firstlogin > (FOREIGN_REG_DAY - 5) * 24 * 3600){ - mail_muser(cuser, "[¥X¤J¹ÒºÞ²z§½]", "etc/foreign_expired_warn"); - } - else if (login_start_time - cuser.firstlogin > FOREIGN_REG_DAY * 24 * 3600){ - cuser.userlevel &= ~(PERM_LOGINOK | PERM_POST); - vmsg("ĵ§i¡G½Ð¦Ü¥X¤J¹ÒºÞ²z§½¥Ó½Ð¥Ã¤[©~¯d"); - } - } -} -#endif - - -static void -user_login(void) -{ - struct tm ptime, lasttime; - int nowusers, ifbirth = 0, i; - - /* NOTE! ¦b setup_utmp ¤§«e, ¤£À³¸Ó¦³¥ô¦ó blocking/slow function, - * §_«h¥iÂǾ÷ race condition ¹F¨ì multi-login */ - - /* get local time */ - ptime = *localtime4(&now); - - /* ªì©l¤Æ: random number ¼W¥[user¸ò®É¶¡ªº®t²§ */ - mysrand(); - - log_usies("ENTER", fromhost); -#ifndef VALGRIND - setproctitle("%s: %s", margs, cuser.userid); -#endif - resolve_fcache(); - /* resolve_boards(); */ - numboards = SHM->Bnumber; - - if(getenv("SSH_CLIENT") != NULL){ - struct sockaddr_in xsin; - char frombuf[50]; - sscanf(getenv("SSH_CLIENT"), "%s", frombuf); - xsin.sin_family = AF_INET; - xsin.sin_port = htons(23); - if (strrchr(frombuf, ':')) - inet_pton(AF_INET, strrchr(frombuf, ':') + 1, &xsin.sin_addr); - else - inet_pton(AF_INET, frombuf, &xsin.sin_addr); - getremotename(&xsin, fromhost, remoteusername); /* RFC931 */ - } - - /* ªì©l¤Æ uinfo¡Bflag¡Bmode */ - setup_utmp(LOGIN); - enter_uflag = cuser.uflag; - lasttime = *localtime4(&cuser.lastlogin); - redrawwin(); - - /* show welcome_login */ - if( (ifbirth = (ptime.tm_mday == cuser.day && - ptime.tm_mon + 1 == cuser.month)) ){ - char buf[PATHLEN]; - snprintf(buf, sizeof(buf), "etc/Welcome_birth.%d", getHoroscope(cuser.month, cuser.day)); - more(buf, NA); - } - else { -#ifndef MULTI_WELCOME_LOGIN - more("etc/Welcome_login", NA); -#else - if( SHM->GV2.e.nWelcomes ){ - char buf[80]; - snprintf(buf, sizeof(buf), "etc/Welcome_login.%d", - (int)login_start_time % SHM->GV2.e.nWelcomes); - more(buf, NA); - } -#endif - } - refresh(); - currutmp->alerts |= load_mailalert(cuser.userid); - - if ((nowusers = SHM->UTMPnumber) > SHM->max_user) { - SHM->max_user = nowusers; - SHM->max_time = now; - } - - if (!(HasUserPerm(PERM_SYSOP) && HasUserPerm(PERM_SYSOPHIDE)) && - !currutmp->invisible) - { - /* do_aloha is costly. do it later? */ - do_aloha("<<¤W¯¸³qª¾>> -- §Ú¨Ó°Õ¡I"); - } - - if (SHM->loginmsg.pid){ - if(search_ulist_pid(SHM->loginmsg.pid)) - getmessage(SHM->loginmsg); - else - SHM->loginmsg.pid=0; - } - - if (cuser.userlevel) { /* not guest */ - move(t_lines - 4, 0); - clrtobot(); - welcome_msg(); - resolve_over18(); - - if( ifbirth ){ - birthday_make_a_wish(&ptime, &lasttime); - if( getans("¬O§_nÅã¥Ü¡u¹Ø¬P¡v©ó¨Ï¥ÎªÌ¦W³æ¤W¡H(y/N)") == 'y' ) - currutmp->birth = 1; - } - check_bad_login(); - check_mailbox_quota(); - check_register(); - record_lasthost(fromhost); - restore_backup(); - - } else if (strcmp(cuser.userid, STR_GUEST) == 0) { /* guest */ - - init_guest_info(); -#if 0 // def DBCSAWARE - u_detectDBCSAwareEvilClient(); -#else - pressanykey(); -#endif - } else { - // XXX no userlevel, no guest - what is this? - // clear(); - // outs("¦¹±b¸¹°±Åv¤¤"); - // pressanykey(); - // exit(1); - - check_mailbox_quota(); - } - - if(ptime.tm_yday!=lasttime.tm_yday) - STATINC(STAT_TODAYLOGIN_MAX); - - if (!PERM_HIDE(currutmp)) { - /* If you wanna do incremental upgrade - * (like, added a function/flag that wants user to confirm againe) - * put it here. - */ - -#if defined(DBCSAWARE) && defined(DBCSAWARE_UPGRADE_STARTTIME) - // define the real time you upgraded in your pttbbs.conf - if(cuser.lastlogin < DBCSAWARE_UPGRADE_STARTTIME) - { - if (u_detectDBCSAwareEvilClient()) - cuser.uflag &= ~DBCSAWARE_FLAG; - else - cuser.uflag |= DBCSAWARE_FLAG; - } -#endif - /* login time update */ - - if(ptime.tm_yday!=lasttime.tm_yday) - STATINC(STAT_TODAYLOGIN_MIN); - - - cuser.lastlogin = login_start_time; - - } - -#if FOREIGN_REG_DAY > 0 - foreign_warning(); -#endif - - passwd_update(usernum, &cuser); - - if(cuser.uflag2 & FAVNEW_FLAG) { - fav_load(); - if (get_fav_root() != NULL) { - int num; - num = updatenewfav(1); - if (num > NEW_FAV_THRESHOLD && - getans("§ä¨ì %d Ó·s¬ÝªO¡A½T©wn¥[¤J§Úªº³Ì·R¶Ü¡H[Y/n]", num) == 'n') { - fav_free(); - fav_load(); - } - } - } - - for (i = 0; i < NUMVIEWFILE; i++) - if ((cuser.loginview >> i) & 1) - more(loginview_file[(int)i][0], YEA); -} - -static void -do_aloha(const char *hello) -{ - FILE *fp; - char userid[80]; - char genbuf[200]; - - setuserfile(genbuf, "aloha"); - if ((fp = fopen(genbuf, "r"))) { - while (fgets(userid, 80, fp)) { - userinfo_t *uentp; - if ((uentp = (userinfo_t *) search_ulist_userid(userid)) && - isvisible(uentp, currutmp)) { - my_write(uentp->pid, hello, uentp->userid, WATERBALL_ALOHA, uentp); - } - } - fclose(fp); - } -} - -static void -do_term_init(void) -{ - term_init(); - initscr(); - if(use_shell_login_mode) - raise(SIGWINCH); -} - -inline static void -start_client(void) -{ -#ifdef CPULIMIT - struct rlimit rml; - rml.rlim_cur = CPULIMIT * 60 - 5; - rml.rlim_max = CPULIMIT * 60; - setrlimit(RLIMIT_CPU, &rml); -#endif - - STATINC(STAT_LOGIN); - /* system init */ - nice(2); /* Ptt: lower priority */ - login_start_time = time(0); - currmode = 0; - - Signal(SIGHUP, abort_bbs); - Signal(SIGTERM, abort_bbs); - Signal(SIGPIPE, abort_bbs); - - Signal(SIGINT, abort_bbs_debug); - Signal(SIGQUIT, abort_bbs_debug); - Signal(SIGILL, abort_bbs_debug); - Signal(SIGABRT, abort_bbs_debug); - Signal(SIGFPE, abort_bbs_debug); - Signal(SIGBUS, abort_bbs_debug); - Signal(SIGSEGV, abort_bbs_debug); - Signal(SIGXCPU, abort_bbs_debug); - - signal_restart(SIGUSR1, talk_request); - signal_restart(SIGUSR2, write_request); - - dup2(0, 1); - - do_term_init(); - Signal(SIGALRM, abort_bbs); - alarm(600); - - login_query(); /* Ptt ¥[¤Wlogin time out */ - m_init(); /* init the user mail path */ - user_login(); - auto_close_polls(); /* ¦Û°Ê¶}²¼ */ - - Signal(SIGALRM, SIG_IGN); - main_menu(); -} - -/* ¨ú±o remote user name ¥H§P©w¨¥÷ */ -/* - * rfc931() speaks a common subset of the RFC 931, AUTH, TAP, IDENT and RFC - * 1413 protocols. It queries an RFC 931 etc. compatible daemon on a remote - * host to look up the owner of a connection. The information should not be - * used for authentication purposes. This routine intercepts alarm signals. - * - * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. - */ - -#define RFC931_TIMEOUT 10 -#define RFC931_PORT 113 /* Semi-well-known port */ -#define ANY_PORT 0 /* Any old port will do */ - -#if 0 -/* timeout - handle timeouts */ -static void -timeout(int sig) -{ - longjmp(byebye, sig); -} -#endif - -static void -getremotename(const struct sockaddr_in * from, char *rhost, char *rname) -{ - - /* get remote host name */ - -#ifdef FAST_LOGIN - XAUTH_HOST(strcpy(rhost, (char *)inet_ntoa(from->sin_addr))); -#else - struct sockaddr_in our_sin; - struct sockaddr_in rmt_sin; - unsigned rmt_port, rmt_pt; - unsigned our_port, our_pt; - FILE *fp; - char buffer[512], user[80], *cp; - int s; - static struct hostent *hp; - - - hp = NULL; - if (setjmp(byebye) == 0) { - Signal(SIGALRM, timeout); - alarm(3); - hp = gethostbyaddr((char *)&from->sin_addr, sizeof(struct in_addr), - from->sin_family); - alarm(0); - } - strcpy(rhost, hp ? hp->h_name : (char *)inet_ntoa(from->sin_addr)); - - /* - * Use one unbuffered stdio stream for writing to and for reading from - * the RFC931 etc. server. This is done because of a bug in the SunOS - * 4.1.x stdio library. The bug may live in other stdio implementations, - * too. When we use a single, buffered, bidirectional stdio stream ("r+" - * or "w+" mode) we read our own output. Such behaviour would make sense - * with resources that support random-access operations, but not with - * sockets. - */ - - s = sizeof(our_sin); - if (getsockname(0, (struct sockaddr *) & our_sin, &s) < 0) - return; - - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) - return; - - if (!(fp = fdopen(s, "r+"))) { - close(s); - return; - } - /* Set up a timer so we won't get stuck while waiting for the server. */ - if (setjmp(byebye) == 0) { - Signal(SIGALRM, timeout); - alarm(RFC931_TIMEOUT); - - /* - * Bind the local and remote ends of the query socket to the same IP - * addresses as the connection under investigation. We go through all - * this trouble because the local or remote system might have more - * than one network address. The RFC931 etc. client sends only port - * numbers; the server takes the IP addresses from the query socket. - */ - our_pt = ntohs(our_sin.sin_port); - our_sin.sin_port = htons(ANY_PORT); - - rmt_sin = *from; - rmt_pt = ntohs(rmt_sin.sin_port); - rmt_sin.sin_port = htons(RFC931_PORT); - - setbuf(fp, (char *)0); - s = fileno(fp); - - if (bind(s, (struct sockaddr *) & our_sin, sizeof(our_sin)) >= 0 && - connect(s, (struct sockaddr *) & rmt_sin, sizeof(rmt_sin)) >= 0) { - /* - * Send query to server. Neglect the risk that a 13-byte write - * would have to be fragmented by the local system and cause - * trouble with buggy System V stdio libraries. - */ - fprintf(fp, "%u,%u\r\n", rmt_pt, our_pt); - fflush(fp); - /* - * Read response from server. Use fgets()/sscanf() so we can work - * around System V stdio libraries that incorrectly assume EOF - * when a read from a socket returns less than requested. - */ - if (fgets(buffer, sizeof(buffer), fp) && !ferror(fp) - && !feof(fp) - && sscanf(buffer, "%u , %u : USERID :%*[^:]:%79s", &rmt_port, - &our_port, user) == 3 && rmt_pt == rmt_port - && our_pt == our_port) { - - /* - * Strip trailing carriage return. It is part of the - * protocol, not part of the data. - */ - if ((cp = (char *)strchr(user, '\r'))) - *cp = 0; - strlcpy(rname, user, sizeof(user)); - } - } - alarm(0); - } - fclose(fp); -#endif -} - -static int -bind_port(int port) -{ - int sock, on, sz; - struct linger lin; - struct sockaddr_in xsin; - - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - - on = 1; - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); - setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)); - - lin.l_onoff = 0; - setsockopt(sock, SOL_SOCKET, SO_LINGER, &lin, sizeof(lin)); - - sz = 1024; - setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&sz, sizeof(sz)); - sz = 4096; - setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&sz, sizeof(sz)); - - OPTIMIZE_LISTEN_SOCKET(sock, sz); - - xsin.sin_family = AF_INET; - xsin.sin_addr.s_addr = htonl(INADDR_ANY); - xsin.sin_port = htons(port); - if (bind(sock, (struct sockaddr *) & xsin, sizeof xsin) < 0) { - syslog(LOG_INFO, "bbsd bind_port can't bind to %d", port); - exit(1); - } - if (listen(sock, SOCKET_QLEN) < 0) { - syslog(LOG_INFO, "bbsd bind_port can't listen to %d", port); - exit(1); - } - return sock; -} - - -/*******************************************************/ - - -static int shell_login(int argc, char *argv[], char *envp[]); -static int daemon_login(int argc, char *argv[], char *envp[]); -static int check_ban_and_load(int fd); -static int check_banip(char *host); - -int -main(int argc, char *argv[], char *envp[]) -{ - start_time = time(NULL); - - /* avoid SIGPIPE */ - Signal(SIGPIPE, SIG_IGN); - - /* avoid erroneous signal from other mbbsd */ - Signal(SIGUSR1, SIG_IGN); - Signal(SIGUSR2, SIG_IGN); - -#if defined(__GLIBC__) && defined(CRITICAL_MEMORY) - #define MY__MMAP_THRESHOLD (1024 * 8) - #define MY__MMAP_MAX (0) - #define MY__TRIM_THRESHOLD (1024 * 8) - #define MY__TOP_PAD (0) - - mallopt (M_MMAP_THRESHOLD, MY__MMAP_THRESHOLD); - mallopt (M_MMAP_MAX, MY__MMAP_MAX); - mallopt (M_TRIM_THRESHOLD, MY__TRIM_THRESHOLD); - mallopt (M_TOP_PAD, MY__TOP_PAD); -#endif - - attach_SHM(); - if( (argc == 3 && shell_login(argc, argv, envp)) || - (argc != 3 && daemon_login(argc, argv, envp)) ) - start_client(); - - return 0; -} - -static int -shell_login(int argc, char *argv[], char *envp[]) -{ - int fd; - - STATINC(STAT_SHELLLOGIN); - /* Give up root privileges: no way back from here */ - setgid(BBSGID); - setuid(BBSUID); - chdir(BBSHOME); - -#if defined(linux) && defined(DEBUG) -// mtrace(); -#endif - - use_shell_login_mode = 1; - initsetproctitle(argc, argv, envp); - - snprintf(margs, sizeof(margs), "%s ssh ", argv[0]); - /* - * copy fromindent: Standard input:1138: Error:Unexpected end of file the - * original "bbs" - */ - if (argc > 1) { - strcpy(fromhost, argv[1]); - if (argc > 3) - strlcpy(remoteusername, argv[3], sizeof(remoteusername)); - } - close(2); - /* don't close fd 1, at least init_tty need it */ - if( ((fd = open("log/stderr", O_WRONLY | O_CREAT | O_APPEND, 0644)) >= 0) && fd != 2 ){ - dup2(fd, 2); - close(fd); - } - - init_tty(); - if (check_ban_and_load(0)) { - sleep(10); - return 0; - } -#ifdef DETECT_CLIENT - FNV1A_CHAR(123, client_code); -#endif - return 1; -} - -static int -daemon_login(int argc, char *argv[], char *envp[]) -{ - int msock, csock; /* socket for Master and Child */ - FILE *fp; - int len_of_sock_addr, overloading = 0, i; - char buf[256]; -#if OVERLOADBLOCKFDS - int blockfd[OVERLOADBLOCKFDS]; - int nblocked = 0; -#endif - struct sockaddr_in xsin; - xsin.sin_family = AF_INET; - - /* setup standalone */ - start_daemon(); - signal_restart(SIGCHLD, reapchild); - - /* choose port */ - if( argc < 2 ) - listen_port = 3006; - else{ -#ifdef NO_FORK - listen_port = atoi(argv[1]); -#else - for( i = 1 ; i < (argc - 1) ; ++i ) - switch( fork() ){ - case -1: - perror("fork()"); - break; - case 0: - goto out; - default: - break; - } - out: - listen_port = atoi(argv[i]); -#endif - } - - /* port binding */ - if( (msock = bind_port(listen_port)) < 0 ){ - syslog(LOG_INFO, "mbbsd bind_port failed.\n"); - exit(1); - } - - /* Give up root privileges: no way back from here */ - setgid(BBSGID); - setuid(BBSUID); - chdir(BBSHOME); - - /* proctitle */ - initsetproctitle(argc, argv, envp); -#ifndef VALGRIND - snprintf(margs, sizeof(margs), "%s %d ", argv[0], listen_port); - setproctitle("%s: listening ", margs); -#endif - - /* It's better to do something before fork */ -#ifdef CONVERT - big2gb_init(NULL); - gb2big_init(NULL); - big2uni_init(NULL); - uni2big_init(NULL); -#endif - -#ifndef NO_FORK -#ifdef PRE_FORK - if( listen_port == 23 ){ // only pre-fork in port 23 - for( i = 0 ; i < PRE_FORK ; ++i ) - if( fork() <= 0 ) - break; - } -#endif -#endif - - snprintf(buf, sizeof(buf), - "run/mbbsd.%d.%d.pid", listen_port, (int)getpid()); - if ((fp = fopen(buf, "w"))) { - fprintf(fp, "%d\n", (int)getpid()); - fclose(fp); - } - - /* main loop */ - while( 1 ){ - len_of_sock_addr = sizeof(xsin); - if( -#if defined(Solaris) && __OS_MAJOR_VERSION__ == 5 && __OS_MINOR_VERSION__ < 7 - (csock = accept(msock, (struct sockaddr *)&xsin, - &len_of_sock_addr)) < 0 -#else - (csock = accept(msock, (struct sockaddr *)&xsin, - (socklen_t *)&len_of_sock_addr)) < 0 -#endif - ) { - if (errno != EINTR) - sleep(1); - continue; - } - - XAUTH_TRYREMOTENAME(); - - overloading = check_ban_and_load(csock); -#if OVERLOADBLOCKFDS - if( (!overloading && nblocked) || - (overloading && nblocked == OVERLOADBLOCKFDS) ){ - for( i = 0 ; i < OVERLOADBLOCKFDS ; ++i ) - if( blockfd[i] != csock && blockfd[i] != msock ) - /* blockfd[i] should not be msock, but it happened */ - close(blockfd[i]); - nblocked = 0; - } -#endif - - if( overloading ){ -#if OVERLOADBLOCKFDS - blockfd[nblocked++] = csock; -#else - close(csock); -#endif - continue; - } - -#ifdef NO_FORK - break; -#else - if (fork() == 0) - break; - else - close(csock); -#endif - } - /* here is only child running */ - -#ifndef VALGRIND - setproctitle("%s: ...login wait... ", margs); -#endif - close(msock); - dup2(csock, 0); - close(csock); - - XAUTH_GETREMOTENAME(getremotename(&xsin, fromhost, remoteusername)); - - if( check_banip(fromhost) ){ - sleep(10); - exit(0); - } - telnet_init(); - return 1; -} - -/* - * check if we're banning login and if the load is too high. if login is - * permitted, return 0; else return -1; approriate message is output to fd. - */ -static int -check_ban_and_load(int fd) -{ - FILE *fp; - static time4_t chkload_time = 0; - static int overload = 0; /* overload or banned, update every 1 - * sec */ - static int banned = 0; - -#ifdef INSCREEN - write(fd, INSCREEN, sizeof(INSCREEN)); -#else -#define BANNER \ -"¡i" BBSNAME "¡j¡· ¥x¤j¬y¦æºô ¡·(" MYHOSTNAME ") ½Õ´T(" MYIP ") \r\n" - write(fd, BANNER, sizeof(BANNER)); -#endif - - if ((time(0) - chkload_time) > 1) { - overload = 0; - banned = 0; - - if(cpuload(NULL) > MAX_CPULOAD) - overload = 1; - else if (SHM->UTMPnumber >= MAX_ACTIVE -#ifdef DYMAX_ACTIVE - || (SHM->GV2.e.dymaxactive > 2000 && - SHM->UTMPnumber >= SHM->GV2.e.dymaxactive) -#endif - ) { - ++SHM->GV2.e.toomanyusers; - overload = 2; - } else if(!access(BBSHOME "/" BAN_FILE, R_OK)) - banned = 1; - - chkload_time = time(0); - } - - if(overload == 1) - write(fd, "¨t²Î¹L¸ü, ½Ðµy«á¦A¨Ó\r\n", 22); - else if(overload == 2) - write(fd, "¥Ñ©ó¤H¼Æ¹L¦h¡A½Ð±zµy«á¦A¨Ó¡C", 28); - else if (banned && (fp = fopen(BBSHOME "/" BAN_FILE, "r"))) { - char buf[256]; - while (fgets(buf, sizeof(buf), fp)) - write(fd, buf, strlen(buf)); - fclose(fp); - } - - if (banned || overload) - return -1; - - return 0; -} - -static int check_banip(char *host) -{ - unsigned int thisip = 0; - char *ptr, *myhost = strdup(host); - char *strtok_pos = NULL; - - for( ptr = strtok_r(myhost, ".", &strtok_pos) ; ptr != NULL ; ptr = strtok_r(NULL, ".", &strtok_pos) ) - thisip = thisip * 256 + atoi(ptr); - free(myhost); - - return uintbsearch(thisip, &banip[1], banip[0]) ? 1 : 0; -} - -/* vim: sw=4 - */ diff --git a/mbbsd/menu.c b/mbbsd/menu.c deleted file mode 100644 index 6aaf3399..00000000 --- a/mbbsd/menu.c +++ /dev/null @@ -1,718 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#define CheckMenuPerm(x) \ - ( (x == MENU_UNREGONLY)? \ - ((cuser.userlevel == 0 ||HasUserPerm(PERM_LOGINOK))?0:1) :\ - ((x) ? HasUserPerm(x) : 1)) - -/* help & menu processring */ -static int refscreen = NA; -extern char *boardprefix; -extern struct utmpfile_t *utmpshm; - -static const char *title_tail_msgs[] = { - "¬ÝªO", - "¨t¦C", - "¤åºK", -}; -static const char *title_tail_attrs[] = { - ANSI_COLOR(37), - ANSI_COLOR(32), - ANSI_COLOR(36), -}; -enum { - TITLE_TAIL_BOARD = 0, - TITLE_TAIL_SELECT, - TITLE_TAIL_DIGEST, -}; - -void -showtitle(const char *title, const char *mid) -{ - /* we have to... - * - display title in left, cannot truncate. - * - display mid message, cannot truncate - * - display tail (board info), if possible. - */ - int llen, rlen, mlen, mpos = 0; - int pos = 0; - int tail_type; - const char *mid_attr = ANSI_COLOR(33); - int is_currboard_special = 0; - char buf[64]; - - - /* prepare mid */ -#ifdef DEBUG - { - sprintf(buf, " current pid: %6d ", getpid()); - mid = buf; - mid_attr = ANSI_COLOR(41;5); - } -#else - if (ISNEWMAIL(currutmp)) { - mid = " §A¦³·s«H¥ó "; - mid_attr = ANSI_COLOR(41;5); - } else if ( HasUserPerm(PERM_ACCTREG) ) { - int nreg = dashs((char *)fn_register) / 163; - if(nreg > 100) - { - sprintf(buf, " ¦³ %03d ¥¼¼f®Ö ", nreg); - mid_attr = ANSI_COLOR(41;5); - mid = buf; - } - } -#endif - - /* prepare tail */ - if (currmode & MODE_SELECT) - tail_type = TITLE_TAIL_SELECT; - else if (currmode & MODE_DIGEST) - tail_type = TITLE_TAIL_DIGEST; - else - tail_type = TITLE_TAIL_BOARD; - - if(currbid > 0) - { - assert(0<=currbid-1 && currbid-1<MAX_BOARD); - is_currboard_special = ( - (getbcache(currbid)->brdattr & BRD_HIDE) && - (getbcache(currbid)->brdattr & BRD_POSTMASK)); - } - - /* now, calculate real positioning info */ - llen = strlen(title); - mlen = strlen(mid); - mpos = (t_columns -1 - mlen)/2; - - /* first, print left. */ - clear(); - outs(TITLE_COLOR "¡i"); - outs(title); - outs("¡j"); - pos = llen + 4; - - /* print mid */ - while(pos++ < mpos) - outc(' '); - outs(mid_attr); - outs(mid); - pos += mlen; - outs(TITLE_COLOR); - - /* try to locate right */ - rlen = strlen(currboard) + 4 + 4; - if(currboard[0] && pos+rlen < t_columns) - { - // print right stuff - while(pos++ < t_columns-rlen) - outc(' '); - outs(title_tail_attrs[tail_type]); - outs(title_tail_msgs[tail_type]); - outs("¡m"); - - if (is_currboard_special) - outs(ANSI_COLOR(32)); - outs(currboard); - outs(title_tail_attrs[tail_type]); - outs("¡n" ANSI_RESET "\n"); - } else { - // just pad it. - while(pos++ < t_columns) - outc(' '); - outs(ANSI_RESET "\n"); - } - -} - -/* °Êµe³B²z */ -#define FILMROW 11 -static const unsigned char menu_row = 12; -static const unsigned char menu_column = 20; - -static void -show_status(void) -{ - int i; - struct tm *ptime = localtime4(&now); - char mystatus[160]; - char *myweek = "¤Ñ¤@¤G¤T¥|¤¤»"; - const char *msgs[] = {"Ãö³¬", "¥´¶}", "©Þ±¼", "¨¾¤ô", "¦n¤Í"}; - - i = ptime->tm_wday << 1; - snprintf(mystatus, sizeof(mystatus), - ANSI_COLOR(34;46) "[%d/%d ¬P´Á%c%c %d:%02d]" - ANSI_COLOR(1;33;45) "%-14s" - ANSI_COLOR(30;47) " ½u¤W" ANSI_COLOR(31) - "%d" ANSI_COLOR(30) "¤H, §Ú¬O" ANSI_COLOR(31) "%s" - ANSI_COLOR(30) , - ptime->tm_mon + 1, ptime->tm_mday, myweek[i], myweek[i + 1], - ptime->tm_hour, ptime->tm_min, currutmp->birth ? - "¥Í¤én½Ð«Èò" : SHM->today_is, - SHM->UTMPnumber, cuser.userid); - outmsg(mystatus); - i = strlen(mystatus) - (3*7+25); // 3 = ANSI_COLOR, 25 = stuff inside - sprintf(mystatus, "[¦©¾÷]" ANSI_COLOR(31) "%s ", - msgs[currutmp->pager]); - outslr("", i, mystatus, strlen(msgs[currutmp->pager]) + 7); - outs(ANSI_RESET); -} - -/* - * current caller of movie: - * board.c: movie(0); // called when IN_CLASSROOT() - * // with currstat = CLASS -> don't show movies - * xyz.c: movie(999999); // logout - * menu.c: movie(cmdmode); // ... - */ -void -movie(int cmdmode) -{ - // movie «e´Xµ§¬O Note ªOºëµØ°Ï¡u<¨t²Î> °ÊºA¬ÝªO¡v(SYS) ¥Ø¿ý¤Uªº¤å³¹ - // movie_map ¬O¥Î¨Ó¨Ì cmdmode ¬D¥X¯S©wªº°ÊºA¬ÝªO¡Aindex ¸ò mode_map ¤@¼Ë¡C - const int movie_map[] = { - 2, 10, 11, -1, 3, -1, 12, - 7, 9, 8, 4, 5, 6, - }; - -#define N_SYSMOVIE (sizeof(movie_map) / sizeof(movie_map[0])) - int i; - if ((currstat != CLASS) && (cuser.uflag & MOVIE_FLAG) && - !SHM->Pbusystate && SHM->last_film > 0) { - if (cmdmode < N_SYSMOVIE && - 0 < movie_map[cmdmode] && movie_map[cmdmode] <= SHM->last_film) { - i = movie_map[cmdmode]; - } else if (cmdmode == 999999) { /* Goodbye my friend */ - i = 0; - } else { - i = N_SYSMOVIE + (int)(((float)SHM->last_film - N_SYSMOVIE + 1) * (random() / (RAND_MAX + 1.0))); - } -#undef N_SYSMOVIE - - move(1, 0); - clrtoln(1 + FILMROW); /* ²M±¼¤W¦¸ªº */ - out_lines(SHM->notes[i], 11); /* ¥u¦L11¦æ´N¦n */ - outs(reset_color); - } - show_status(); - refresh(); -} - -typedef struct { - int (*cmdfunc)(); - int level; - char *desc; /* next/key/description */ -} commands_t; - -static int -show_menu(int moviemode, const commands_t * p) -{ - register int n = 0; - register char *s; - - movie(moviemode); - - move(menu_row, 0); - while ((s = p[n].desc)) { - if (CheckMenuPerm(p[n].level)) { - prints("%*s (" ANSI_COLOR(1;36) "%c" ANSI_COLOR(0) ")%s\n", menu_column, "", s[1], - s+2); - } - n++; - } - return n - 1; -} - - -enum { - M_ADMIN = 0, M_AMUSE, M_CHC, M_JCEE, M_MAIL, M_MMENU, M_NMENU, - M_PMENU, M_PSALE, M_SREG, M_TMENU, M_UMENU, M_XMENU, M_XMAX -}; - -static const int mode_map[] = { - ADMIN, AMUSE, CHC, JCEE, MAIL, MMENU, NMENU, - PMENU, PSALE, SREG, TMENU, UMENU, XMENU, -}; - -static void -domenu(int cmdmode, const char *cmdtitle, int cmd, const commands_t cmdtable[]) -{ - int lastcmdptr, moviemode; - int n, pos, total, i; - int err; - - moviemode = cmdmode; - assert(cmdmode < M_XMAX); - cmdmode = mode_map[cmdmode]; - - setutmpmode(cmdmode); - - showtitle(cmdtitle, BBSName); - - total = show_menu(moviemode, cmdtable); - - show_status(); - lastcmdptr = pos = 0; - - do { - i = -1; - switch (cmd) { - case Ctrl('I'): - t_idle(); - refscreen = YEA; - i = lastcmdptr; - break; - case Ctrl('N'): - New(); - refscreen = YEA; - i = lastcmdptr; - break; - case Ctrl('A'): - if (mail_man() == FULLUPDATE) - refscreen = YEA; - i = lastcmdptr; - break; - case KEY_DOWN: - i = lastcmdptr; - case KEY_HOME: - case KEY_PGUP: - do { - if (++i > total) - i = 0; - } while (!CheckMenuPerm(cmdtable[i].level)); - break; - case KEY_END: - case KEY_PGDN: - i = total; - break; - case KEY_UP: - i = lastcmdptr; - do { - if (--i < 0) - i = total; - } while (!CheckMenuPerm(cmdtable[i].level)); - break; - case KEY_LEFT: - case 'e': - case 'E': - if (cmdmode == MMENU) - cmd = 'G'; - else if ((cmdmode == MAIL) && chkmailbox()) - cmd = 'R'; - else - return; - default: - if ((cmd == 's' || cmd == 'r') && - (currstat == MMENU || currstat == TMENU || currstat == XMENU)) { - if (cmd == 's') - ReadSelect(); - else - Read(); - refscreen = YEA; - i = lastcmdptr; - break; - } - if (cmd == '\n' || cmd == '\r' || cmd == KEY_RIGHT) { - move(b_lines, 0); - clrtoeol(); - - currstat = XMODE; - - if ((err = (*cmdtable[lastcmdptr].cmdfunc) ()) == QUIT) - return; - currutmp->mode = currstat = cmdmode; - - if (err == XEASY) { - refresh(); - safe_sleep(1); - } else if (err != XEASY + 1 || err == FULLUPDATE) - refscreen = YEA; - - if (err != -1) - cmd = cmdtable[lastcmdptr].desc[0]; - else - cmd = cmdtable[lastcmdptr].desc[1]; - } - if (cmd >= 'a' && cmd <= 'z') - cmd &= ~0x20; - while (++i <= total) - if (cmdtable[i].desc[1] == cmd) - break; - - if (!CheckMenuPerm(cmdtable[i].level)) { - for (i = 0; cmdtable[i].desc; i++) - if (CheckMenuPerm(cmdtable[i].level)) - break; - if (!cmdtable[i].desc) - return; - } - - if (cmd == 'H' && i > total){ - /* TODO: Add menu help */ - } - } - - if (i > total || !CheckMenuPerm(cmdtable[i].level)) - continue; - - if (refscreen) { - showtitle(cmdtitle, BBSName); - - show_menu(moviemode, cmdtable); - - show_status(); - refscreen = NA; - } - cursor_clear(menu_row + pos, menu_column); - n = pos = -1; - while (++n <= (lastcmdptr = i)) - if (CheckMenuPerm(cmdtable[n].level)) - pos++; - - cursor_show(menu_row + pos, menu_column); - } while (((cmd = igetch()) != EOF) || refscreen); - - abort_bbs(0); -} -/* INDENT OFF */ - -/* administrator's maintain menu */ -static const commands_t adminlist[] = { - {m_user, PERM_SYSOP, "UUser ¨Ï¥ÎªÌ¸ê®Æ"}, - {search_user_bypwd, PERM_ACCOUNTS|PERM_POLICE_MAN, - "SSearch User ¯S®í·j´M¨Ï¥ÎªÌ"}, - {search_user_bybakpwd,PERM_ACCOUNTS,"OOld User data ¬d¾\\³Æ¥÷¨Ï¥ÎªÌ¸ê®Æ"}, - {m_board, PERM_SYSOP|PERM_BOARD, "BBoard ³]©w¬ÝªO"}, - {m_register, PERM_ACCOUNTS|PERM_ACCTREG, - "RRegister ¼f®Öµù¥Uªí³æ"}, - {cat_register, PERM_SYSOP, "CCatregister µLªk¼f®Ö®É¥Îªº"}, - {x_file, PERM_SYSOP|PERM_VIEWSYSOP, - "XXfile ½s¿è¨t²ÎÀÉ®×"}, - {give_money, PERM_SYSOP|PERM_VIEWSYSOP, - "GGivemoney ¬õ¥]Âû"}, - {m_loginmsg, PERM_SYSOP, "MMessage Login ¶i¯¸¤ô²y"}, - {NULL, 0, NULL} -}; - -/* mail menu */ -static const commands_t maillist[] = { - {m_new, PERM_READMAIL, "RNew ¾\\Ū·s¶i¶l¥ó"}, - {m_read, PERM_READMAIL, "RRead ¦h¥\\¯àŪ«H¿ï³æ"}, - {m_send, PERM_LOGINOK, "RSend ¯¸¤º±H«H"}, - {mail_list, PERM_LOGINOK, "RMail List ¸s²Õ±H«H"}, - {x_love, PERM_LOGINOK, "PPaper ±¡®Ñ²£¥Í¾¹"}, - {setforward, PERM_LOGINOK, "FForward " ANSI_COLOR(1;32) - "³]©w«H½c¦Û°ÊÂà±H" ANSI_RESET}, - {m_sysop, 0, "YYes, sir! ¼g«Hµ¹¯¸ªø"}, - {m_internet, PERM_INTERNET, "RInternet ±H«H¨ì¯¸¥~"}, - {mail_mbox, PERM_INTERNET, "RZip UserHome §â©Ò¦³¨p¤H¸ê®Æ¥´¥]¦^¥h"}, - {built_mail_index, PERM_LOGINOK, "SSavemail ««Ø«H½c¯Á¤Þ"}, - {mail_all, PERM_SYSOP, "RAll ±H«Hµ¹©Ò¦³¨Ï¥ÎªÌ"}, - {NULL, 0, NULL} -}; - -/* Talk menu */ -static const commands_t talklist[] = { - {t_users, 0, "UUsers §¹¥þ²á¤Ñ¤â¥U"}, - {t_pager, PERM_BASIC, "PPager ¤Á´«©I¥s¾¹"}, - {t_idle, 0, "IIdle µo§b"}, - {t_query, 0, "QQuery ¬d¸ßºô¤Í"}, - {t_qchicken, 0, "WWatch Pet ¬d¸ßÃdª«"}, - // PERM_PAGE - ¤ô²y³£n PERM_LOGIN ¤F - // ¨S¹D²z¥i¥H talk ¤£¯à¤ô²y¡C - {t_talk, PERM_LOGINOK, "TTalk §ä¤H²á²á"}, - // PERM_CHAT «D login ¤]¦³¡A·|¦³¤H¥Î¦¹§n§O¤H¡C - {t_chat, PERM_LOGINOK, "CChat §ä®a¯ù§{³ð¯ù¥h"}, -#ifdef PLAY_ANGEL - {t_changeangel, PERM_LOGINOK, "UAChange Angel §ó´«¤p¤Ñ¨Ï"}, - {t_angelmsg, PERM_ANGEL, "LLeave message ¯d¨¥µ¹¤p¥D¤H"}, -#endif - {t_display, 0, "DDisplay Åã¥Ü¤W´X¦¸¼ö°T"}, - {NULL, 0, NULL} -}; - -/* name menu */ -static int t_aloha() { - friend_edit(FRIEND_ALOHA); - return 0; -} - -static int t_special() { - friend_edit(FRIEND_SPECIAL); - return 0; -} - -static const commands_t namelist[] = { - {t_override, PERM_LOGINOK,"OOverRide ¦n¤Í¦W³æ"}, - {t_reject, PERM_LOGINOK, "BBlack Ãa¤H¦W³æ"}, - {t_aloha,PERM_LOGINOK, "AALOHA ¤W¯¸³qª¾¦W³æ"}, - {t_fix_aloha,PERM_LOGINOK,"XXFixALOHA ×¥¿¤W¯¸³qª¾"}, - {t_special,PERM_LOGINOK, "SSpecial ¨ä¥L¯S§O¦W³æ"}, - {NULL, 0, NULL} -}; - -void Customize(); // user.c -int u_customize() -{ - Customize(); - return 0; -} - -int u_fixgoodpost(void); // assess.c -/* User menu */ -static const commands_t userlist[] = { - {u_customize, PERM_BASIC, "UUCustomize Ó¤H¤Æ³]©w"}, - {u_info, PERM_LOGINOK, "IInfo ³]©wÓ¤H¸ê®Æ»P±K½X"}, - {calendar, PERM_LOGINOK, "CCalendar Ó¤H¦æ¨Æ¾ä"}, - {u_loginview, PERM_BASIC, "LLogin View ¿ï¾Ü¶i¯¸µe±"}, - {u_editplan, PERM_LOGINOK, "QQueryEdit ½s¿è¦W¤ùÀÉ"}, - {u_editsig, PERM_LOGINOK, "SSignature ½s¿èñ¦WÀÉ"}, -#if HAVE_FREECLOAK - {u_cloak, PERM_LOGINOK, "KKCloak Áô¨³N"}, -#else - {u_cloak, PERM_CLOAK, "KKCloak Áô¨³N"}, -#endif - {u_register, MENU_UNREGONLY, "RRegister ¶ñ¼g¡mµù¥U¥Ó½Ð³æ¡n"}, -#ifdef ASSESS - {u_cancelbadpost, PERM_LOGINOK, "BBye BadPost ¥Ó½Ð§R°£¦H¤å"}, - {u_fixgoodpost, PERM_LOGINOK, "FFix GoodPost ×´_Àu¤å"}, -#endif // ASSESS - {u_list, PERM_SYSOP, "XUsers ¦C¥Xµù¥U¦W³æ"}, -#ifdef MERGEBBS -// {m_sob, PERM_LOGUSER|PERM_SYSOP, "SSOB Import ¨FÅyÅܨ³N"}, - {m_sob, PERM_BASIC, "SSOB Import ¨FÅyÅܨ³N"}, -#endif - {NULL, 0, NULL} -}; - -#ifdef DEBUG -int _debug_check_keyinput(); -int _debug_testregcode(); -int _debug_reportstruct() -{ - clear(); - prints("boardheader_t:\t%d\n", sizeof(boardheader_t)); - prints("fileheader_t:\t%d\n", sizeof(fileheader_t)); - prints("userinfo_t:\t%d\n", sizeof(userinfo_t)); - prints("screenline_t:\t%d\n", sizeof(screenline_t)); - prints("SHM_t:\t%d\n", sizeof(SHM_t)); - prints("bid_t:\t%d\n", sizeof(bid_t)); - prints("userec_t:\t%d\n", sizeof(userec_t)); - pressanykey(); - return 0; -} - -#endif - -/* XYZ tool menu */ -static const commands_t xyzlist[] = { -#ifndef DEBUG - /* All these are useless in debug mode. */ -#ifdef HAVE_LICENSE - {x_gpl, 0, "LLicense GNU ¨Ï¥Î°õ·Ó"}, -#endif -#ifdef HAVE_INFO - {x_program, 0, "PProgram ¥»µ{¦¡¤§ª©¥»»Pª©Åv«Å§i"}, -#endif - {x_boardman,0, "MMan Boards ¡m¬ÝªOºëµØ°Ï±Æ¦æº]¡n"}, -// {x_boards,0, "HHot Boards ¡m¬ÝªO¤H®ð±Æ¦æº]¡n"}, - {x_history, 0, "HHistory ¡m§Ú̪º¦¨ªø¡n"}, - {x_note, 0, "NNote ¡m»Ä²¢W»¶¬y¨¥ªO¡n"}, - {x_login,0, "SSystem ¡m¨t²Î«n¤½§i¡n"}, - {x_week, 0, "WWeek ¡m¥»¶g¤¤Q¤j¼öªù¸ÜÃD¡n"}, - {x_issue, 0, "IIssue ¡m¤µ¤é¤Q¤j¼öªù¸ÜÃD¡n"}, - {x_today, 0, "TToday ¡m¤µ¤é¤W½u¤H¦¸²Îp¡n"}, - {x_yesterday, 0, "YYesterday ¡m¬Q¤é¤W½u¤H¦¸²Îp¡n"}, - {x_user100 ,0, "UUsers ¡m¨Ï¥ÎªÌ¦Ê¤j±Æ¦æº]¡n"}, -#else - {_debug_check_keyinput, 0, - "MMKeycode Àˬd«öÁä±±¨î½X¤u¨ã"}, - {_debug_testregcode, 0, - "RRegcode Àˬdµù¥U½X¤½¦¡"}, - {_debug_reportstruct, 0, - "RReportStruct ³ø§i¦UºØµ²ºcªº¤j¤p"}, -#endif - - {p_sysinfo, 0, "XXinfo ¡m¬d¬Ý¨t²Î¸ê°T¡n"}, - {NULL, 0, NULL} -}; - -/* Ptt money menu */ -static const commands_t moneylist[] = { - {p_give, 0, "00Give µ¹¨ä¥L¤H¿ú"}, - {save_violatelaw, 0,"11ViolateLaw ú»@³æ"}, -#if !HAVE_FREECLOAK - {p_cloak, 0, "22Cloak ¤Á´« Áô¨/²{¨ $19 /¦¸"}, -#endif - {p_from, 0, "33From ¼È®Éקï¬G¶m $49 /¦¸"}, - {ordersong,0, "44OSong ¼Ú®á°ÊºAÂIºq¾÷ $200 /¦¸"}, - {p_exmail, 0, "55Exmail ÁʶR«H½c $1000/«Ê"}, - {NULL, 0, NULL} -}; - -static const commands_t cmdlist[] = { - {admin, PERM_SYSOP|PERM_ACCOUNTS|PERM_BOARD|PERM_VIEWSYSOP|PERM_ACCTREG|PERM_POLICE_MAN, - "00Admin ¡i ¨t²ÎºûÅ@°Ï ¡j"}, - {Announce, 0, "AAnnounce ¡i ºëµØ¤½§GÄæ ¡j"}, -#ifdef DEBUG - {Favorite, 0, "FFavorite ¡i §Úªº³Ì¤£·R ¡j"}, -#else - {Favorite, 0, "FFavorite ¡i §Ú ªº ³Ì·R ¡j"}, -#endif - {Class, 0, "CClass ¡i ¤À²Õ°Q½×°Ï ¡j"}, - {Mail, PERM_BASIC, "MMail ¡i ¨p¤H«H¥ó°Ï ¡j"}, - {Talk, 0, "TTalk ¡i ¥ð¶¢²á¤Ñ°Ï ¡j"}, - {User, PERM_BASIC, "UUser ¡i Ó¤H³]©w°Ï ¡j"}, - {Xyz, 0, "XXyz ¡i ¨t²Î¸ê°T°Ï ¡j"}, - {Play_Play, PERM_LOGINOK, "PPlay ¡i ®T¼Ö»P¥ð¶¢ ¡j"}, - {Name_Menu, PERM_LOGINOK, "NNamelist ¡i ½s¯S§O¦W³æ ¡j"}, -#ifdef DEBUG - {Goodbye, 0, "GGoodbye ¦A¨£¦A¨£¦A¨£¦A¨£"}, -#else - {Goodbye, 0, "GGoodbye Â÷¶}¡A¦A¨£¡K "}, -#endif - {NULL, 0, NULL} -}; - -int main_menu(void) { - domenu(M_MMENU, "¥D¥\\¯àªí", (ISNEWMAIL(currutmp) ? 'M' : 'C'), cmdlist); - return 0; -} - -static int p_money() { - domenu(M_PSALE, BBSMNAME2 "¶q³c©±", '0', moneylist); - return 0; -}; - -// static int forsearch(); -static int playground(); -static int chessroom(); - -/* Ptt Play menu */ -static const commands_t playlist[] = { - {note, PERM_LOGINOK, "NNote ¡i ¨è¨è¬y¨¥ªO ¡j"}, - /* // useless. - {forsearch,PERM_LOGINOK, "SSearchEngine¡i" ANSI_COLOR(1;35) " " - BBSMNAME2 "·j´M¾¹ " ANSI_RESET "¡j"}, - */ - {topsong,PERM_LOGINOK, "TTop Songs ¡i" ANSI_COLOR(1;32) " ÂIºq±Æ¦æº] " ANSI_RESET "¡j"}, - {p_money,PERM_LOGINOK, "PPay ¡i" ANSI_COLOR(1;31) " " - BBSMNAME2 "¶q³c©± " ANSI_RESET "¡j"}, - {chicken_main,PERM_LOGINOK, "CChicken " - "¡i" ANSI_COLOR(1;34) " " BBSMNAME2 "¾iÂû³õ " ANSI_RESET "¡j"}, - {playground,PERM_LOGINOK, "AAmusement ¡i" ANSI_COLOR(1;33) " " - BBSMNAME2 "¹C¼Ö³õ " ANSI_RESET "¡j"}, - {chessroom, PERM_LOGINOK, "BBChess ¡i" ANSI_COLOR(1;34) " " - BBSMNAME2 "´Ñ°| " ANSI_RESET "¡j"}, - {NULL, 0, NULL} -}; - -static const commands_t chesslist[] = { - {chc_main, PERM_LOGINOK, "11CChessFight ¡i" ANSI_COLOR(1;33) " ¶H´ÑÁܧ½ " ANSI_RESET "¡j"}, - {chc_personal, PERM_LOGINOK, "22CChessSelf ¡i" ANSI_COLOR(1;34) " ¶H´Ñ¥´ÃÐ " ANSI_RESET "¡j"}, - {chc_watch, PERM_LOGINOK, "33CChessWatch ¡i" ANSI_COLOR(1;35) " ¶H´ÑÆ[´Ñ " ANSI_RESET "¡j"}, - {gomoku_main, PERM_LOGINOK, "44GomokuFight ¡i" ANSI_COLOR(1;33) "¤¤l´ÑÁܧ½" ANSI_RESET "¡j"}, - {gomoku_personal, PERM_LOGINOK, "55GomokuSelf ¡i" ANSI_COLOR(1;34) "¤¤l´Ñ¥´ÃÐ" ANSI_RESET "¡j"}, - {gomoku_watch, PERM_LOGINOK, "66GomokuWatch ¡i" ANSI_COLOR(1;35) "¤¤l´ÑÆ[´Ñ" ANSI_RESET "¡j"}, - {gochess_main, PERM_LOGINOK, "77GoChessFight ¡i" ANSI_COLOR(1;33) " ³ò´ÑÁܧ½ " ANSI_RESET "¡j"}, - {gochess_personal, PERM_LOGINOK, "88GoChessSelf ¡i" ANSI_COLOR(1;34) " ³ò´Ñ¥´ÃÐ " ANSI_RESET "¡j"}, - {gochess_watch, PERM_LOGINOK, "99GoChessWatch ¡i" ANSI_COLOR(1;35) " ³ò´ÑÆ[´Ñ " ANSI_RESET "¡j"}, - {NULL, 0, NULL} -}; - -static int chessroom() { - domenu(M_CHC, BBSMNAME2 "´Ñ°|", '1', chesslist); - return 0; -} - -static const commands_t plist[] = { - -/* {p_ticket_main, PERM_LOGINOK,"00Pre ¡i Á`²Î¾÷ ¡j"}, - {alive, PERM_LOGINOK, "00Alive ¡i q²¼Âû ¡j"}, -*/ - {ticket_main, PERM_LOGINOK, "11Gamble ¡i " BBSMNAME2 "½ä³õ ¡j"}, - {guess_main, PERM_LOGINOK, "22Guess number¡i ²q¼Æ¦r ¡j"}, - {othello_main, PERM_LOGINOK, "33Othello ¡i ¶Â¥Õ´Ñ ¡j"}, -// {dice_main, PERM_LOGINOK, "44Dice ¡i ª±»ë¤l ¡j"}, - {vice_main, PERM_LOGINOK, "44Vice ¡i µo²¼¹ï¼ú ¡j"}, - {g_card_jack, PERM_LOGINOK, "55Jack ¡i ¶Â³Ç§J ¡j"}, - {g_ten_helf, PERM_LOGINOK, "66Tenhalf ¡i ¤QÂI¥b ¡j"}, - {card_99, PERM_LOGINOK, "77Nine ¡i ¤E¤Q¤E ¡j"}, - {NULL, 0, NULL} -}; - -static int playground() { - domenu(M_AMUSE, BBSMNAME2 "¹C¼Ö³õ",'1',plist); - return 0; -} - -static const commands_t slist[] = { - /* - // x_dict: useless - {x_dict,0, "11Dictionary " - "¡i" ANSI_COLOR(1;33) " ½ì¨ý¤j¦r¨å " ANSI_RESET "¡j"}, - */ - {x_mrtmap, 0, "22MRTmap " - "¡i" ANSI_COLOR(1;34) " ±¶¹B¦a¹Ï " ANSI_RESET "¡j"}, - {NULL, 0, NULL} -}; - -/* // nothing to search... -static int forsearch() { - domenu(M_SREG, BBSMNAME2 "·j´M¾¹", '1', slist); - return 0; -} -*/ - -/* main menu */ - -int -admin(void) -{ - domenu(M_ADMIN, "¨t²ÎºûÅ@", 'X', adminlist); - return 0; -} - -int -Mail(void) -{ - domenu(M_MAIL, "¹q¤l¶l¥ó", 'R', maillist); - return 0; -} - -int -Talk(void) -{ - domenu(M_TMENU, "²á¤Ñ»¡¸Ü", 'U', talklist); - return 0; -} - -int -User(void) -{ - domenu(M_UMENU, "Ó¤H³]©w", 'U', userlist); - return 0; -} - -int -Xyz(void) -{ - domenu(M_XMENU, "¤u¨ãµ{¦¡", 'M', xyzlist); - return 0; -} - -int -Play_Play(void) -{ - domenu(M_PMENU, "ºô¸ô¹C¼Ö³õ", 'A', playlist); - return 0; -} - -int -Name_Menu(void) -{ - domenu(M_NMENU, "¥Õ¦â®£©Æ", 'O', namelist); - return 0; -} - diff --git a/mbbsd/merge.c b/mbbsd/merge.c deleted file mode 100644 index 913f94f5..00000000 --- a/mbbsd/merge.c +++ /dev/null @@ -1,237 +0,0 @@ -/* $Id$ */ -#define _XOPEN_SOURCE -#define _ISOC99_SOURCE -/* this is a interface provided when we merge BBS */ -#include "bbs.h" -#include "fpg.h" - -int -m_sob(void) -{ - char genbuf[256], buf[256], userid[25], passbuf[24], msg[2048]=""; - int count=0, i, isimported=0, corrected; - FILE *fp; - sobuserec man; - time4_t d; - - clear(); - move(1,0); - - outs( - " ½Ðª`·N ³o¬O¥uµ¹¶§¥ú¨FÅy¨Ï¥ÎªÌ!\n" - " Åý¨FÅyªº¨Ï¥ÎªÌÂಾӤH¸ê²£¥H¤Î«n«H¥Î¸ê®Æ, ¨É¦³¥µ¥¦w¥þªºÀô¹Ò.\n" - " ¦pªG±z¤£»Ýn, ½Ðª½Â÷¶}.\n" - " -----------------------------------------------------------------\n" - " ¯S§O¥mÀ{:\n" - " ¬°¤F±b¸¹¦w¥þ,±z¥u¦³³sÄò¤Q¦¸±K½X¿ù»~ªº¾÷·|,½Ð¤p¤ß¿é¤J.\n" - " ³sÄò¦¸¿ù»~±zªºÅܨ¥\\¯à´N·|³Q¶}»@³æ¨Ãª½±µ³qª¾¯¸ªø.\n" - " ½Ð¤£n¦bÅܨ¹Lµ{¤¤¤£¥¿±`Â_½u, ¨è·NÂ_½uÅÜ¥bÃ~¤H¯¸ªø¤£±Ïò.\n" - ); - - if(getkey("¬O§_nÄ~Äò?(y/N)")!='y') return 0; - if(search_ulistn(usernum,2)) - {vmsg("½Ðµn¥X¨ä¥Lµøµ¡, ¥H§KÅܨ¥¢±Ñ"); return 0;} - do - { - if(!getdata(10,0, " ¨FÅyªºID [¤j¤p¼gn§¹¥þ¥¿½T]:", userid, 20, - DOECHO)) return 0; - if(bad_user_id(userid)) continue; - sprintf(genbuf, "sob/passwd/%c/%s.inf",userid[0], userid); - if(!(fp=fopen(genbuf, "r"))) - { - isimported = 1; - strcat(genbuf, ".done"); - if(!(fp=fopen(genbuf, "r"))) - { - vmsg("¬dµL¦¹¤H©Î¤w¸g¶×¤J¹L..½Ðª`·N¤j¤p¼g "); - isimported = 0; - continue; - } - } - count = fread(&man, sizeof(man), 1, fp); - fclose(fp); - }while(!count); - count = 0; - do{ - if(!getdata(11,0, " ¨FÅyªº±K½X:", passbuf, sizeof(passbuf), - NOECHO)) return 0; - if(++count>=10) - { - cuser.userlevel |= PERM_VIOLATELAW; - cuser.vl_count++; - passwd_update(usernum, &cuser); - post_violatelaw(cuser.userid, "[PTTĵ¹î]", "´ú¸Õ±b¸¹¿ù»~¤Q¦¸", - "¹HªkÆ[¹î"); - mail_violatelaw(cuser.userid, "[PTTĵ¹î]", "´ú¸Õ±b¸¹¿ù»~¤Q¦¸", - "¹HªkÆ[¹î"); - - return 0; - } - if(!(corrected = checkpasswd(man.passwd, passbuf))) - vmsg("±K½X¿ù»~"); - } while(!corrected); - move(12,0); - clrtobot(); - - if(!isimported) - { - if(!dashf(genbuf)) // avoid multi-login - { - vmsg("½Ð¤£n¹Á¸Õ¦h«id¿å¶×¤J"); - return 0; - } - sprintf(buf,"%s.done",genbuf); - rename(genbuf,buf); -#ifdef MERGEMONEY - - reload_money(); - - sprintf(buf, - "±zªº¨FÅyÆxÄMÁ³ %10d ´«ºâ¦¨ " MONEYNAME " ¹ô¬° %9d (¶×²v 22:1), \n" - " ¨FÅy¨©´ß¦³ %10d ´«ºâ¬° " MONEYNAME " ¹ô¬° %9d (¶×²v 222105:1), \n" - " 즳 %10d ¶×¤J«á¦@¦³ %d\n", - (int)man.goldmoney, (int)man.goldmoney/22, - (int)man.silvermoney, (int)man.silvermoney/222105, - cuser.money, - (int)(cuser.money + man.goldmoney/22 + man.silvermoney/222105)); - demoney(man.goldmoney/22 + man.silvermoney/222105 ); - strcat(msg, buf); -#endif - - i = cuser.exmailbox + man.exmailbox + man.exmailboxk/2000; - if (i > MAX_EXKEEPMAIL) i = MAX_EXKEEPMAIL; - sprintf(buf, "±zªº¨FÅy«H½c¦³ %d (%dk), 즳 %d ¶×¤J«á¦@¦³ %d\n", - man.exmailbox, man.exmailboxk, cuser.exmailbox, i); - strcat(msg, buf); - cuser.exmailbox = i; - - if(man.userlevel & PERM_MAILLIMIT) - { - sprintf(buf, "¶}±Ò«H½cµL¤W\n"); - strcat(msg, buf); - cuser.userlevel |= PERM_MAILLIMIT; - } - - if (cuser.firstlogin > man.firstlogin) - d = man.firstlogin; - else - d = cuser.firstlogin; - cuser.firstlogin = d; - - if (cuser.numlogins < man.numlogins) - i = man.numlogins; - else - i = cuser.numlogins; - - sprintf(buf, "¨FÅy¶i¯¸¦¸¼Æ %d ¦¹±b¸¹ %d ±N¨ú %d \n", man.numlogins, - cuser.numlogins, i); - strcat(msg,buf); - cuser.numlogins = i; - - if (cuser.numposts < man.numposts ) - i = man.numposts; - else - i = cuser.numposts; - sprintf(buf, "¨FÅy¤å³¹¦¸¼Æ %d ¦¹±b¸¹ %d ±N¨ú %d\n", - man.numposts,cuser.numposts,i); - strcat(msg,buf); - cuser.numposts = i; - outs(msg); - while (search_ulistn(usernum,2)) - {vmsg("½Ð±N«ÂФW¯¸¨ä¥L½uÃö³¬! ¦AÄ~Äò");} - passwd_update(usernum, &cuser); - } - sethomeman(genbuf, cuser.userid); - mkdir(genbuf, 0600); - sprintf(buf, "tar zxvf %c/%s.tar.gz>/dev/null", - userid[0], userid); - chdir("sob/home"); - system(buf); - chdir(BBSHOME); - - if (getans("¬O§_¶×¤JÓ¤H«H½c? (Y/n)")!='n') - { - sethomedir(buf, cuser.userid); - sprintf(genbuf, "sob/home/%c/%s/.DIR", - userid[0], userid); - merge_dir(buf, genbuf, 1); - strcat(msg, "¶×¤JÓ¤H«H½c\n"); - } - if(getans("¬O§_¶×¤JÓ¤H«H½cºëµØ°Ï(Ó¤H§@«~¶°)? (·|Âл\\²{¦³³]©w) (y/N)")=='y') - { - fileheader_t fh; - sprintf(buf, - "rm -rd home/%c/%s/man>/dev/null ; " - "mv sob/home/%c/%s/man home/%c/%s>/dev/null;" - "mv sob/home/%c/%s/gem home/%c/%s/man>/dev/null", - cuser.userid[0], cuser.userid, - userid[0], userid, - cuser.userid[0], cuser.userid, - userid[0], userid, - cuser.userid[0], cuser.userid); - system(buf); - strcat(msg, "¶×¤JÓ¤H«H½cºëµØ°Ï(Ó¤H§@«~¶°)\n"); - sprintf(buf,"home/%c/%s/man/gem", cuser.userid[0], cuser.userid); - if(dashd(buf)) - { - strcat(fh.title, "¡» Ó¤H§@«~¶°"); - strcat(fh.filename, "gem"); - sprintf(fh.owner, cuser.userid); - sprintf(buf, "home/%c/%s/man/.DIR", cuser.userid[0], cuser.userid); - append_record(buf, &fh, sizeof(fh)); - } - } - if(getans("¬O§_¶×¤J¦n¤Í¦W³æ? (·|Âл\\²{¦³³]©w, ID¥i¯à¬O¤£¦P¤H)? (y/N)")=='y') - { - sethomefile(genbuf, cuser.userid, "overrides"); - sprintf(buf, "sob/home/%c/%s/overrides",userid[0],userid); - Copy(buf, genbuf); - strcat(buf, genbuf); - friend_load(FRIEND_OVERRIDE); - strcat(msg, "¶×¤J¦n¤Í¦W³æ\n"); - } - sprintf(buf, "±b¸¹¶×¤J³ø§i %s -> %s ", userid, cuser.userid); - post_msg(GLOBAL_SECURITY, buf, msg, "[¨t²Î¦w¥þ§½]"); - - vmsg("®¥³ß±z§¹¦¨±b¸¹Åܨ.."); - return 0; -} - -void -m_sob_brd(char *bname, char *fromdir) -{ - char fbname[25], buf[256]; - fileheader_t fh; - - fromdir[0]=0; - do{ - - if(!getdata(20,0, "SOBªºªO¦W [^¤å¤j¤p¼gn§¹¥þ¥¿½T]:", fbname, 20, - DOECHO)) return; - } - while((invalid_brdname(fbname)&1)); - - sprintf(buf, "sob/man/%s.tar.gz", fbname); - if(!dashf(buf)) - { - vmsg("µL¦¹¬ÝªO"); - return; - } - chdir(BBSHOME"/sob/boards"); - sprintf(buf, "tar zxf %s.tar.gz >/dev/null",fbname); - system(buf); - chdir(BBSHOME"/sob/man"); - sprintf(buf, "tar zxf %s.tar.gz >/dev/null", fbname); - system(buf); - chdir(BBSHOME); - sprintf(buf, "mv sob/man/%s man/boards/%c/%s", fbname, - bname[0], bname); - system(buf); - sprintf(fh.title, "¡» %s ºëµØ°Ï", fbname); - sprintf(fh.filename, fbname); - sprintf(fh.owner, cuser.userid); - sprintf(buf, "man/boards/%c/%s/.DIR", bname[0], bname); - append_record(buf, &fh, sizeof(fh)); - sprintf(fromdir, "sob/boards/%s/.DIR", fbname); - vmsgf("§Y±N¶×¤J %s ªO¸ê®Æ..«öÁä«á»Ýn¤@ÂI®É¶¡",fbname); -} diff --git a/mbbsd/more.c b/mbbsd/more.c deleted file mode 100644 index d506754a..00000000 --- a/mbbsd/more.c +++ /dev/null @@ -1,77 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -/* use new pager: piaip's more. */ -int more(char *fpath, int promptend) -{ - int r = pmore(fpath, promptend); - - switch(r) - { - - case RET_DOSYSOPEDIT: - r = FULLUPDATE; - - if (!HasUserPerm(PERM_SYSOP) || - strcmp(fpath, "etc/ve.hlp") == 0) - break; - -#ifdef GLOBAL_SECURITY - if (strcmp(currboard, GLOBAL_SECURITY) == 0) - break; -#endif // GLOBAL_SECURITY - - log_filef("log/security", LOG_CREAT, - "%u %24.24s %d %s admin edit file=%s\n", - (int)now, ctime4(&now), getpid(), cuser.userid, fpath); - - // no need to allow anything... - // at least, no need to change title. - vedit2(fpath, NA, NULL, 0); - break; - - case RET_SELECTBRD: - r = FULLUPDATE; - if (HasUserPerm(PERM_BASIC)) - { - if (currstat == READING) - return Select(); - } - break; - - case RET_COPY2TMP: - r = FULLUPDATE; - if (HasUserPerm(PERM_BASIC)) - { - char buf[PATHLEN]; - getdata(b_lines - 1, 0, "§â³o½g¤å³¹¦¬¤J¨ì¼È¦sÀÉ¡H[y/N] ", - buf, 4, LCECHO); - if (buf[0] != 'y') - break; - setuserfile(buf, ask_tmpbuf(b_lines - 1)); - Copy(fpath, buf); - } - break; - - case RET_DOCHESSREPLAY: - r = FULLUPDATE; - if (HasUserPerm(PERM_BASIC)) - { - ChessReplayGame(fpath); - } - break; - -#if defined(USE_BBSLUA) - case RET_DOBBSLUA: - r = FULLUPDATE; - if (HasUserPerm(PERM_BASIC)) - { - bbslua(fpath); - } - break; -#endif - } - - return r; -} - diff --git a/mbbsd/name.c b/mbbsd/name.c deleted file mode 100644 index 4e9d7134..00000000 --- a/mbbsd/name.c +++ /dev/null @@ -1,1067 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -static word_t *current = NULL; -static char * const msg_more = "-- More --"; - -typedef char (*arrptr)[]; -/* name complete for user ID */ - -//----------------------------------------------------------------------- - -void NameList_init(struct NameList *self) -{ - self->size = 0; - self->capacity = 0; - self->base = NULL; -} - -void NameList_delete(struct NameList *self) -{ - self->size = 0; - self->capacity = 0; - if(self->base) - free(self->base); - self->base = NULL; -} - -void NameList_clear(struct NameList *self) -{ - NameList_delete(self); - NameList_init(self); -} - -void NameList_resizefor(struct NameList *self, int size) -{ - int capacity = size * (IDLEN+1); -#define MIN_CAPACITY 4096 - if (capacity == 0) { - if(self->base) free(self->base); - self->base = NULL; - self->capacity = 0; - } else { - int old_capacity = self->capacity; - assert(capacity > 0); - if (self->capacity == 0) - self->capacity = MIN_CAPACITY; - //if (self->capacity > capacity && self->capacity > MIN_CAPACITY) - // self->capacity /= 2; - if (self->capacity < capacity) - self->capacity *= 2; - - if(old_capacity != self->capacity || self->base == NULL) { - char (*tmp)[IDLEN+1] = (char(*)[IDLEN+1])malloc((IDLEN+1)*self->capacity); - assert(tmp); - if (self->size) - memcpy(tmp, self->base, (IDLEN+1)*self->size); - if (self->base) - free(self->base); - self->base = tmp; - } - } -} - -void NameList_add(struct NameList *self, const char *name) -{ - NameList_resizefor(self, self->size+1); - strlcpy(self->base[self->size], name, IDLEN+1); - self->size++; -} - -const char* NameList_get(struct NameList *self, int idx) -{ - assert(0<=idx && idx<self->size); - return self->base[idx]; -} - -static int NameList_MaxLen(const struct NameList *list, int offset, int count) -{ - int i; - int maxlen = 0; - - for(i=offset; i<list->size; i++) { - int len = strlen(list->base[i]); - if (len > maxlen) - maxlen = len; - } - assert(maxlen <= IDLEN); - return maxlen; -} - -int NameList_match(const struct NameList *src, struct NameList *dst, int key, int pos) -{ - int uckey, lckey; - int i; - - NameList_clear(dst); - - uckey = chartoupper(key); - if (key >= 'A' && key <= 'Z') - lckey = key | 0x20; - else - lckey = key; - - for(i=0; i<src->size; i++) { - int ch = src->base[i][pos]; - if (ch == lckey || ch == uckey) - NameList_add(dst, src->base[i]); - } - - return dst->size; -} - -int NameList_length(struct NameList *self) -{ - return self->size; -} - -void NameList_sublist(struct NameList *src, struct NameList *dst, char *tag) -{ - int i; - int len; - NameList_clear(dst); - - len = strlen(tag); - for(i=0; i<src->size; i++) - if(len==0 || strncasecmp(src->base[i], tag, len)==0) - NameList_add(dst, src->base[i]); -} - -int NameList_remove(struct NameList *self, const char *name) -{ - int i; - for(i=0; i<self->size; i++) - if(strcasecmp(self->base[i], name)==0) { - strcpy(self->base[i], self->base[self->size-1]); - - self->size--; - NameList_resizefor(self, self->size); - return 1; - } - return 0; -} - -int NameList_search(const struct NameList *self, const char *name) -{ - int i; - for(i=0; i<self->size; i++) - if (strcasecmp(self->base[i], name)==0) - return 1; - return 0; -} - -//----------------------------------------------------------------------- - -static int -UserMaxLen(char cwlist[][IDLEN + 1], int cwnum, int morenum, - int count) -{ - int len, max = 0; - - while (count-- > 0 && morenum < cwnum) { - len = strlen(cwlist[morenum++]); - if (len > max) - max = len; - } - /* assert max IDLEN */ - if(max > IDLEN) - max = IDLEN+1; - return max; -} - -static int -UserSubArray(char cwbuf[][IDLEN + 1], char cwlist[][IDLEN + 1], - int cwnum, int key, int pos) -{ - int key2, num = 0; - int n, ch; - - key = chartoupper(key); - - if (key >= 'A' && key <= 'Z') - key2 = key | 0x20; - else - key2 = key; - - for (n = 0; n < cwnum; n++) { - ch = cwlist[n][pos]; - if (ch == key || ch == key2) - strlcpy(cwbuf[num++], cwlist[n], sizeof(cwbuf[num])); - } - return num; -} - -void -FreeNameList(void) -{ - word_t *p, *temp; - - for (p = toplev; p; p = temp) { - temp = p->next; - free(p->word); - free(p); - } -} - -void -CreateNameList(void) -{ - if (toplev) - FreeNameList(); - toplev = current = NULL; -} - -void -AddNameList(const char *name) -{ - word_t *node; - - node = (word_t *) malloc(sizeof(word_t)); - node->next = NULL; - node->word = (char *)malloc(strlen(name) + 1); - strcpy(node->word, name); - - if (toplev) - current = current->next = node; - else - current = toplev = node; -} - -int -RemoveNameList(const char *name) -{ - word_t *curr, *prev = NULL; - - for (curr = toplev; curr; curr = curr->next) { - if (!strcmp(curr->word, name)) { - if (prev == NULL) - toplev = curr->next; - else - prev->next = curr->next; - - if (curr == current) - current = prev; - free(curr->word); - free(curr); - return 1; - } - prev = curr; - } - return 0; -} - -static inline int -InList(const word_t * list, const char *name) -{ - const word_t *p; - - for (p = list; p; p = p->next) - if (!strcasecmp(p->word, name)) - return 1; - return 0; -} - -int -InNameList(const char *name) -{ - return InList(toplev, name); -} - -void -ShowNameList(int row, int column, const char *prompt) -{ - word_t *p; - - move(row, column); - clrtobot(); - outs(prompt); - - column = 80; - for (p = toplev; p; p = p->next) { - row = strlen(p->word) + 1; - if (column + row > 76) { - column = row; - outc('\n'); - } else { - column += row; - outc(' '); - } - outs(p->word); - } -} - -void -ToggleNameList(int *reciper, const char *listfile, const char *msg) -{ - FILE *fp; - char genbuf[200]; - - if ((fp = fopen(listfile, "r"))) { - while (fgets(genbuf, STRLEN, fp)) { - char *space = strpbrk(genbuf, str_space); - if (space) *space = '\0'; - if (!genbuf[0]) - continue; - if (!InNameList(genbuf)) { - AddNameList(genbuf); - (*reciper)++; - } else { - RemoveNameList(genbuf); - (*reciper)--; - } - } - fclose(fp); - ShowNameList(3, 0, msg); - } -} - -static int -NumInList(const word_t * list) -{ - register int i; - - for (i = 0; list; i++) - list = list->next; - return i; -} - -int -chkstr(char *otag, const char *tag, const char *name) -{ - char ch; - const char *oname = name; - - while (*tag) { - ch = *name++; - if (*tag != chartoupper(ch)) - return 0; - tag++; - } - if (*tag && *name == '\0') - strcpy(otag, oname); - return 1; -} - -static word_t * -GetSubList(char *tag, word_t * list) -{ - word_t *wlist, *wcurr; - char tagbuf[STRLEN]; - int n; - - wlist = wcurr = NULL; - for (n = 0; tag[n]; n++) - tagbuf[n] = chartoupper(tag[n]); - tagbuf[n] = '\0'; - - while (list) { - if (chkstr(tag, tagbuf, list->word)) { - register word_t *node; - - node = (word_t *) malloc(sizeof(word_t)); - node->word = list->word; - node->next = NULL; - if (wlist) - wcurr->next = node; - else - wlist = node; - wcurr = node; - } - list = list->next; - } - return wlist; -} - -static void -ClearSubList(word_t * list) -{ - struct word_t *tmp_list; - - while (list) { - tmp_list = list->next; - free(list); - list = tmp_list; - } -} - -static int -MaxLen(const word_t * list, int count) -{ - int len = strlen(list->word); - int t; - - while (list && count) { - if ((t = strlen(list->word)) > len) - len = t; - list = list->next; - count--; - } - return len; -} - -/* TODO use namecomplete2() instead */ -void -namecomplete(const char *prompt, char *data) -{ - char *temp; - word_t *cwlist, *morelist; - int x, y, origx, scrx; - int ch; - int count = 0; - int clearbot = NA; - - if (toplev == NULL) - AddNameList(""); - cwlist = GetSubList("", toplev); - morelist = NULL; - temp = data; - - outs(prompt); - clrtoeol(); - getyx(&y, &x); - scrx = origx = x; - data[count] = 0; - - while (1) - { - // print input field again - move(y, scrx); outc(' '); clrtoeol(); move(y, scrx); - outs(ANSI_COLOR(7)); - prints("%-*s", IDLEN + 1, data); - outs(ANSI_RESET); - move(y, scrx + count); - - // get input - if ((ch = igetch()) == EOF) - break; - - if (ch == '\n' || ch == '\r') { - *temp = '\0'; - // outc('\n'); - if (NumInList(cwlist) == 1) - strcpy(data, cwlist->word); - else if (!InList(cwlist, data)) - data[0] = '\0'; - ClearSubList(cwlist); - break; - } - if (ch == ' ') { - int col, len; - - if (NumInList(cwlist) == 1) { - strcpy(data, cwlist->word); - count = strlen(data); - temp = data + count; - continue; - } - clearbot = YEA; - col = 0; - if (!morelist) - morelist = cwlist; - len = MaxLen(morelist, p_lines); - move(2, 0); - clrtobot(); - printdash("¬ÛÃö¸ê°T¤@Äýªí", 0); - while (len + col < t_columns) { - int i; - - for (i = p_lines; (morelist) && (i > 0); i--) { - move(3 + (p_lines - i), col); - outs(morelist->word); - morelist = morelist->next; - } - col += len + 2; - if (!morelist) - break; - len = MaxLen(morelist, p_lines); - } - if (morelist) { - vmsg(msg_more); - } - continue; - } - if (ch == '\177' || ch == '\010') { - if (temp == data) - continue; - temp--; - count--; - *temp = '\0'; - ClearSubList(cwlist); - cwlist = GetSubList(data, toplev); - morelist = NULL; - continue; - } - if (count < STRLEN && isprint(ch)) { - word_t *node; - - *temp++ = ch; - count++; - *temp = '\0'; - node = GetSubList(data, cwlist); - if (node == NULL) { - temp--; - *temp = '\0'; - count--; - continue; - } - ClearSubList(cwlist); - cwlist = node; - morelist = NULL; - } - } - if (ch == EOF) - /* longjmp(byebye, -1); */ - raise(SIGHUP); /* jochang: don't know if this is - * necessary... */ - outc('\n'); - if (clearbot) { - move(2, 0); - clrtobot(); - } - if (*data) { - move(y, origx); - outs(data); - outc('\n'); - } -} - -void -namecomplete2(struct NameList *namelist, const char *prompt, char *data) -{ - char *temp; - int x, y, origx, scrx; - int ch; - int count = 0; - int clearbot = NA; - struct NameList sublist; - int viewoffset = 0; - - NameList_init(&sublist); - - NameList_sublist(namelist, &sublist, ""); - temp = data; - - outs(prompt); - clrtoeol(); - getyx(&y, &x); - scrx = origx = x; - data[count] = 0; - viewoffset = 0; - - while (1) - { - // print input field - move(y, scrx); outc(' '); clrtoeol(); move(y, scrx); - outs(ANSI_COLOR(7)); - prints("%-*s", IDLEN + 1, data); - outs(ANSI_RESET); - move(y, scrx + count); - - // get input - if ((ch = igetch()) == EOF) - break; - - if (ch == '\n' || ch == '\r') { - *temp = '\0'; - if (NameList_length(&sublist)==1) - strcpy(data, NameList_get(&sublist, 0)); - else if (!NameList_search(&sublist, data)) - data[0] = '\0'; - NameList_delete(&sublist); - break; - } - if (ch == ' ') { - int col, len; - - if (NameList_length(&sublist) == 1) { - strcpy(data, NameList_get(&sublist, 0)); - count = strlen(data); - temp = data + count; - continue; - } - clearbot = YEA; - col = 0; - len = NameList_MaxLen(&sublist, viewoffset, p_lines); - move(2, 0); - clrtobot(); - printdash("¬ÛÃö¸ê°T¤@Äýªí", 0); - while (len + col < t_columns) { - int i; - - for (i = p_lines; viewoffset < NameList_length(&sublist) && (i > 0); i--) { - move(3 + (p_lines - i), col); - outs(NameList_get(&sublist, viewoffset)); - viewoffset++; - } - col += len + 2; - if (viewoffset == NameList_length(&sublist)) { - viewoffset = 0; - break; - } - len = NameList_MaxLen(&sublist, viewoffset, p_lines); - } - if (viewoffset < NameList_length(&sublist)) { - vmsg(msg_more); - } - continue; - } - if (ch == '\177' || ch == '\010') { - if (temp == data) - continue; - temp--; - count--; - *temp = '\0'; - NameList_sublist(namelist, &sublist, data); - viewoffset = 0; - continue; - } - if (count < STRLEN && isprint(ch)) { - struct NameList tmplist; - NameList_init(&tmplist); - - *temp++ = ch; - count++; - *temp = '\0'; - - NameList_sublist(&sublist, &tmplist, data); - if (NameList_length(&tmplist)==0) { - NameList_delete(&tmplist); - temp--; - *temp = '\0'; - count--; - continue; - } - NameList_delete(&sublist); - sublist = tmplist; - viewoffset = 0; - } - } - if (ch == EOF) - /* longjmp(byebye, -1); */ - raise(SIGHUP); /* jochang: don't know if this is - * necessary... */ - outc('\n'); - if (clearbot) { - move(2, 0); - clrtobot(); - } - if (*data) { - move(y, origx); - outs(data); - outc('\n'); - } -} - -void -usercomplete(const char *prompt, char *data) -{ - char *temp; - char *cwbuf, *cwlist; - int cwnum, x, y, origx, scrx; - int clearbot = NA, count = 0, morenum = 0; - char ch; - int dashdirty = 0; - - /* TODO ¸`¬Ù°O¾ÐÅé. (¤£¹L³oÓ function ¤£±`¥e°O¾ÐÅé...) */ - cwbuf = malloc(MAX_USERS * (IDLEN + 1)); - cwlist = u_namearray((arrptr) cwbuf, &cwnum, ""); - temp = data; - - outs(prompt); - clrtoeol(); - getyx(&y, &x); - scrx = origx = x; - data[count] = 0; - - while (1) - { - // print input field again - move(y, scrx); outc(' '); clrtoeol(); move(y, scrx); - outs(ANSI_COLOR(7)); - prints("%-*s", IDLEN + 1, data); - outs(ANSI_RESET); - move(y, scrx + count); - - // get input - if ((ch = igetch()) == EOF) - break; - - if (ch == '\n' || ch == '\r') { - int i; - char *ptr; - - *temp = '\0'; - outc('\n'); - ptr = cwlist; - for (i = 0; i < cwnum; i++) { - if (strncasecmp(data, ptr, IDLEN + 1) == 0) { - strcpy(data, ptr); - break; - } - ptr += IDLEN + 1; - } - if (i == cwnum) - data[0] = '\0'; - break; - - } else if (ch == '\177' || ch == '\010') { - if (temp == data) - continue; - temp--; - count--; - *temp = '\0'; - cwlist = u_namearray((arrptr) cwbuf, &cwnum, data); - morenum = 0; - continue; - - } else if (!(count <= IDLEN && isprint((int)ch))) { - - /* invalid input */ - continue; - - } else if (ch != ' ') { - - int n; - - *temp++ = ch; - *temp = '\0'; - n = UserSubArray((arrptr) cwbuf, (arrptr) cwlist, cwnum, ch, count); - - if (n > 0) { - /* found something */ - cwlist = cwbuf; - count++; - cwnum = n; - morenum = 0; - continue; - } - /* no break, no continue, list later. */ - } - - /* finally, list available users. */ - { - int col, len; - - if (ch == ' ' && cwnum == 1) { - if(dashdirty) - { - move(2,0); - clrtoeol(); - printdash(cwlist, 0); - } - strcpy(data, cwlist); - count = strlen(data); - temp = data + count; - continue; - } - - clearbot = YEA; - col = 0; - - len = UserMaxLen((arrptr) cwlist, cwnum, morenum, p_lines); - move(2, 0); - clrtobot(); - printdash("¨Ï¥ÎªÌ¥N¸¹¤@Äýªí", 0); - dashdirty = 0; - - if(ch != ' ') - { - /* no such user */ - move(2,0); - outs("- ¥Ø«eµL¨Ï¥ÎªÌ "); - outs(data); - outs(" "); - temp--; - *temp = '\0'; - dashdirty = 1; - } - - while (len + col < t_columns-1) { - - int i; - - for (i = 0; morenum < cwnum && i < p_lines; i++) { - move(3 + i, col); - prints("%.*s ", IDLEN, - cwlist + (IDLEN + 1) * morenum++); - } - col += len + 2; - if (morenum >= cwnum) - break; - len = UserMaxLen((arrptr) cwlist, cwnum, morenum, p_lines); - } - if (morenum < cwnum) { - move(b_lines, 0); clrtoeol(); - outs(msg_more); - // vmsg(msg_more); - } else - morenum = 0; - - continue; - } - } - free(cwbuf); - if (ch == EOF) - /* longjmp(byebye, -1); */ - raise(SIGHUP); /* jochang: don't know if this is necessary */ - outc('\n'); - if (clearbot) { - move(2, 0); - clrtobot(); - } - if (*data) { - move(y, origx); - outs(data); - outc('\n'); - } -} - -static int -gnc_findbound(char *str, int *START, int *END, - size_t nmemb, gnc_comp_func compar) -{ - int start, end, mid, cmp, strl; - strl = strlen(str); - - start = -1, end = nmemb - 1; - /* The first available element is always in the half-open interval - * (start, end]. (or `end'-th it self if start == end) */ - while (end > start + 1) { - mid = (start + end) / 2; - cmp = (*compar)(mid, str, strl); - if (cmp >= 0) - end = mid; - else - start = mid; - } - if ((*compar)(end, str, strl) != 0) { - *START = *END = -1; - return -1; - } - *START = end; - - start = end; - end = nmemb; - /* The last available element is always in the half-open interval - * [start, end). (or `start'-th it self if start == end) */ - while (end > start + 1) { - mid = (start + end) / 2; - cmp = (*compar)(mid, str, strl); - if (cmp <= 0) - start = mid; - else - end = mid; - } - *END = start; - return 0; -} - -static int -gnc_complete(char *data, int *start, int *end, - gnc_perm_func permission, gnc_getname_func getname) -{ - int i, count, first = -1, last = *end; - if (*start < 0 || *end < 0) - return 0; - for (i = *start, count = 0; i <= *end; ++i) - if ((*permission)(i)) { - if (first == -1) - first = i; - last = i; - ++count; - } - if (count == 1) - strcpy(data, (*getname)(first)); - - *start = first; - *end = last; - return count; -} - - -int -generalnamecomplete(const char *prompt, char *data, int len, size_t nmemb, - gnc_comp_func compar, gnc_perm_func permission, - gnc_getname_func getname) -{ - int x, y, origx, scrx, ch, i, morelist = -1, col, ret = -1; - int start, end, ptr; - int clearbot = NA; - - outs(prompt); - clrtoeol(); - getyx(&y, &x); - scrx = origx = x; - - ptr = 0; - data[ptr] = 0; - - start = 0; end = nmemb - 1; - while (1) - { - // print input field again - move(y, scrx); outc(' '); clrtoeol(); move(y, scrx); - outs(ANSI_COLOR(7)); - // data[ptr] = 0; - prints("%-*s", len, data); - outs(ANSI_RESET); - move(y, scrx + ptr); - - // get input - if ((ch = igetch()) == EOF) - break; - - if (ch == '\n' || ch == '\r') { - data[ptr] = 0; - outc('\n'); - if (ptr != 0) { - gnc_findbound(data, &start, &end, nmemb, compar); - if (gnc_complete(data, &start, &end, permission, getname) - == 1 || (*compar)(start, data, len) == 0) { - strcpy(data, (*getname)(start)); - ret = start; - } else { - data[0] = '\n'; - ret = -1; - } - } else - ptr = -1; - break; - } else if (ch == ' ') { - if (morelist == -1) { - if (gnc_findbound(data, &start, &end, nmemb, compar) == -1) - continue; - i = gnc_complete(data, &start, &end, permission, getname); - if (i == 1) { - ptr = strlen(data); - continue; - } else { - char* first = (*getname)(start); - i = ptr; - while (first[i] && (*compar)(end, first, i + 1) == 0) { - data[i] = first[i]; - ++i; - } - data[i] = '\0'; - - if (i != ptr) { /* did complete several words */ - ptr = i; - } - } - morelist = start; - } else if (morelist > end) - continue; - clearbot = YEA; - move(2, 0); - clrtobot(); - printdash("¬ÛÃö¸ê°T¤@Äýªí", 0); - - col = 0; - while (len + col < t_columns-1) { - for (i = 0; morelist <= end && i < p_lines; ++morelist) { - if ((*permission)(morelist)) { - move(3 + i, col); - prints("%s ", (*getname)(morelist)); - ++i; - } - } - - col += len + 2; - } - if (morelist != end + 1) { - vmsg(msg_more); - } - continue; - - } else if (ch == '\177' || ch == '\010') { /* backspace */ - if (ptr == 0) - continue; - morelist = -1; - --ptr; - data[ptr] = 0; - continue; - } else if (isprint(ch) && ptr <= (len - 2)) { - morelist = -1; - data[ptr] = ch; - ++ptr; - data[ptr] = 0; - if (gnc_findbound(data, &start, &end, nmemb, compar) < 0) - data[--ptr] = 0; - else { - for (i = start; i <= end; ++i) - if ((*permission)(i)) - break; - if (i == end + 1) - data[--ptr] = 0; - } - } - } - - outc('\n'); - if (clearbot) { - move(2, 0); - clrtobot(); - } - if (*data) { - move(y, origx); - outs(data); - outc('\n'); - } - return ret; -} - -/* general complete functions (brdshm) */ -int -completeboard_compar(int where, const char *str, int len) -{ - boardheader_t *bh = &bcache[SHM->bsorted[0][where]]; - return strncasecmp(bh->brdname, str, len); -} - -int -completeboard_permission(int where) -{ - boardheader_t *bptr = &bcache[SHM->bsorted[0][where]]; - return (!(bptr->brdattr & BRD_SYMBOLIC) && - (GROUPOP() || HasBoardPerm(bptr)) && - !(bptr->brdattr & BRD_GROUPBOARD)); -} - -int -complete_board_and_group_permission(int where) -{ - boardheader_t *bptr = &bcache[SHM->bsorted[0][where]]; - return (!(bptr->brdattr & BRD_SYMBOLIC) && - (GROUPOP() || HasBoardPerm(bptr))); - -} - -char * -completeboard_getname(int where) -{ - return bcache[SHM->bsorted[0][where]].brdname; -} - -/* general complete functions (utmpshm) */ -int -completeutmp_compar(int where, const char *str, int len) -{ - userinfo_t *u = &SHM->uinfo[SHM->sorted[SHM->currsorted][0][where]]; - return strncasecmp(u->userid, str, len); -} - -int -completeutmp_permission(int where) -{ - userinfo_t *u = &SHM->uinfo[SHM->sorted[SHM->currsorted][0][where]]; - return (unlikely(HasUserPerm(PERM_SYSOP)) || - unlikely(HasUserPerm(PERM_SEECLOAK)) || -// !SHM->sorted[SHM->currsorted][0][where]->invisible); - isvisible(currutmp, u)); -} - -char * -completeutmp_getname(int where) -{ - return SHM->uinfo[SHM->sorted[SHM->currsorted][0][where]].userid; -} diff --git a/mbbsd/osdep.c b/mbbsd/osdep.c deleted file mode 100644 index f4a9bd85..00000000 --- a/mbbsd/osdep.c +++ /dev/null @@ -1,643 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#ifdef NEED_STRLCAT - -#include <sys/types.h> -#include <string.h> - -/* size_t - * strlcat(char *dst, const char *src, size_t size); - */ -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(src) + MIN(siz, strlen(initial dst)). - * If retval >= siz, truncation occurred. - */ -size_t -strlcat(dst, src, siz) - char *dst; - const char *src; - size_t siz; -{ - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -} - -#endif - -#ifdef NEED_TIMEGM - -#include <time.h> -#include <stdlib.h> - -time_t timegm (struct tm *tm) -{ - time_t ret; - char *tz; - - tz = getenv("TZ"); - putenv("TZ="); - tzset(); - ret = mktime(tm); - - if (tz){ - char *buff = malloc( strlen(tz) + 10); - sprintf( buff, "TZ=%s", tz); - putenv(buff); - free(buff); - } - else - unsetenv("TZ"); - tzset(); - - return ret; -} - -#endif - -#ifdef NEED_STRLCPY - -/* ------------------------------------------------------------------------ */ - -/* size_t - * strlcpy(char *dst, const char *src, size_t size); - */ - -/* - * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -size_t strlcpy(dst, src, siz) - char *dst; - const char *src; - size_t siz; -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} - -#endif - -#ifdef NEED_STRCASESTR - -char * -strcasestr(const char *big, const char *little) -{ - char *ans = (char *)big; - int len = strlen(little); - char *endptr = (char *)big + strlen(big) - len; - - while (ans <= endptr) - if (!strncasecmp(ans, little, len)) - return ans; - else - ans++; - return 0; -} - -#endif - -#ifdef NEED_SCANDIR - -/* - * Scan the directory dirname calling select to make a list of selected - * directory entries then sort using qsort and compare routine dcomp. - * Returns the number of entries and a pointer to a list of pointers to - * struct dirent (through namelist). Returns -1 if there were any errors. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <stdlib.h> -#include <string.h> - -/* - * The DIRSIZ macro is the minimum record length which will hold the directory - * entry. This requires the amount of space in struct dirent without the - * d_name field, plus enough space for the name and a terminating nul byte - * (dp->d_namlen + 1), rounded up to a 4 byte boundary. - */ -#undef DIRSIZ -#define DIRSIZ(dp) \ - ((sizeof(struct dirent) - sizeof(dp)->d_name) + \ - ((strlen((dp)->d_name) + 1 + 3) &~ 3)) -#if 0 -((sizeof(struct dirent) - sizeof(dp)->d_name) + \ - (((dp)->d_namlen + 1 + 3) &~ 3)) -#endif - -int -scandir(dirname, namelist, select, dcomp) - const char *dirname; - struct dirent ***namelist; - int (*select) (struct dirent *); - int (*dcomp) (const void *, const void *); -{ - register struct dirent *d, *p, **names; - register size_t nitems; - struct stat stb; - long arraysz; - DIR *dirp; - - if ((dirp = opendir(dirname)) == NULL) - return(-1); - if (fstat(dirp->dd_fd, &stb) < 0) - return(-1); - - /* - * estimate the array size by taking the size of thedirectory file - * and dividing it by a multiple of the minimum sizeentry. - */ - arraysz = (stb.st_size / 24); - names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *)); - if (names == NULL) - return(-1); - - nitems = 0; - while ((d = readdir(dirp)) != NULL) { - if (select != NULL && !(*select)(d)) - continue; /* just selected names */ - /* - * Make a minimum size copy of the data - */ - p = (struct dirent *)malloc(DIRSIZ(d)); - if (p == NULL) - return(-1); - p->d_ino = d->d_ino; - p->d_off = d->d_off; - p->d_reclen = d->d_reclen; - memcpy(p->d_name, d->d_name, strlen(d->d_name) +1); -#if 0 - p->d_fileno = d->d_fileno; - p->d_type = d->d_type; - p->d_reclen = d->d_reclen; - p->d_namlen = d->d_namlen; - bcopy(d->d_name, p->d_name, p->d_namlen + 1); -#endif - /* - * Check to make sure the array has space left and - * realloc the maximum size. - */ - if (++nitems >= arraysz) { - if (fstat(dirp->dd_fd, &stb) < 0) - return(-1); /* just might have grown */ - arraysz = stb.st_size / 12; - names = (struct dirent **)realloc((char*)names, - arraysz * sizeof(struct dirent*)); - if (names == NULL) - return(-1); - } - names[nitems-1] = p; - } - closedir(dirp); - if (nitems && dcomp != NULL) - qsort(names, nitems, sizeof(struct dirent *),dcomp); - *namelist = names; - return(nitems); -} - -/* - * Alphabetic order comparison routine for those who want it. - */ -int -alphasort(d1, d2) - const void *d1; - const void *d2; -{ - return(strcmp((*(struct dirent **)d1)->d_name, - (*(struct dirent **)d2)->d_name)); -} - -#endif - -#ifdef NEED_FLOCK - -int -flock (int fd, int f) -{ - if( f == LOCK_EX ) - return lockf(fd, F_LOCK, 0L); - - if( f == LOCK_UN ) - return lockf(fd, F_ULOCK, 0L); - - return -1; -} - -#endif - -#ifdef NEED_UNSETENV - -void -unsetenv(name) - char *name; -{ - extern char **environ; - register char **pp; - int len = strlen(name); - - for (pp = environ; *pp != NULL; pp++) - { - if (strncmp(name, *pp, len) == 0 && - ((*pp)[len] == '=' || (*pp)[len] == '\0')) - break; - } - - for (; *pp != NULL; pp++) - *pp = pp[1]; -} - -#endif - -#ifdef NEED_INET_PTON - -#include <arpa/nameser.h> - -/* - * Copyright (c) 1996 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -int -inet_pton(int af, const char *src, void *dst) -{ - static const char digits[] = "0123456789"; - int saw_digit, octets, ch; - u_char tmp[INADDRSZ], *tp; - - saw_digit = 0; - octets = 0; - *(tp = tmp) = 0; - while ((ch = *src++) != '\0') { - const char *pch; - - if ((pch = strchr(digits, ch)) != NULL) { - u_int new = *tp * 10 + (pch - digits); - - if (new > 255) - return (0); - *tp = new; - if (! saw_digit) { - if (++octets > 4) - return (0); - saw_digit = 1; - } - } else if (ch == '.' && saw_digit) { - if (octets == 4) - return (0); - *++tp = 0; - saw_digit = 0; - } else - return (0); - } - if (octets < 4) - return (0); - - memcpy(dst, tmp, INADDRSZ); - - return (1); -} -#endif - -#ifdef NEED_BSD_SIGNAL - -void (*bsd_signal(int sig, void (*func)(int)))(int) -{ - struct sigaction act, oact; - - act.sa_handler = func; - act.sa_flags = SA_RESTART; - sigemptyset(&act.sa_mask); - sigaddset(&act.sa_mask, sig); - if (sigaction(sig, &act, &oact) == -1) - return(SIG_ERR); - return(oact.sa_handler); -} - - -#endif - - -#ifdef Solaris - -#include <sys/stat.h> -#include <sys/swap.h> - - -double swapused(int *total, int *used) -{ - double percent = -1; - register int cnt, i; - register int free; - struct swaptable *swt; - struct swapent *ste; - static char path[256]; // does it really need 'static' ? - cnt = swapctl(SC_GETNSWP, 0); - swt = (struct swaptable *)malloc(sizeof(int) + - cnt * sizeof(struct swapent)); - if (swt == NULL) - { - return 0; - } - swt->swt_n = cnt; - - /* fill in ste_path pointers: we don't care about the paths, so we point - them all to the same buffer */ - ste = &(swt->swt_ent[0]); - i = cnt; - while (--i >= 0) - { - ste++->ste_path = path; - } - /* grab all swap info */ - swapctl(SC_LIST, swt); - - /* walk thru the structs and sum up the fields */ - *total = free = 0; - ste = &(swt->swt_ent[0]); - i = cnt; - while (--i >= 0) - { - /* dont count slots being deleted */ - if (!(ste->ste_flags & ST_INDEL) && - !(ste->ste_flags & ST_DOINGDEL)) - { - *total += ste->ste_pages; - free += ste->ste_free; - } - ste++; - } - - *used = *total - free; - if( total != 0) - percent = (double)*used / (double)*total; - else - percent = 0; - - return percent; -} -#endif - -#if __FreeBSD__ - -#include <kvm.h> - - -double -swapused(int *total, int *used) -{ - double percent = -1; - kvm_t *kd; - struct kvm_swap swapinfo; - int pagesize; - - kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL); - if (kd) { - if (kvm_getswapinfo(kd, &swapinfo, 1, 0) == 0) { - pagesize = getpagesize(); - *total = swapinfo.ksw_total * pagesize; - *used = swapinfo.ksw_used * pagesize; - if (*total != 0) - percent = (double)*used / (double)*total; - } - kvm_close(kd); - } - return percent; -} - -#endif - -#if __FreeBSD__ - -int -cpuload(char *str) -{ - double l[3] = {-1, -1, -1}; - if (getloadavg(l, 3) != 3) - l[0] = -1; - - if (str) { - if (l[0] != -1) - sprintf(str, " %.2f %.2f %.2f", l[0], l[1], l[2]); - else - strcpy(str, " (unknown) "); - } - return (int)l[0]; -} -#endif - - -#ifdef Solaris - -#include <kstat.h> -#include <sys/param.h> - -#define loaddouble(la) ((double)(la) / FSCALE) - -int -cpuload(char *str) -{ - kstat_ctl_t *kc; - kstat_t *ks; - kstat_named_t *kn; - double l[3] = {-1, -1, -1}; - - kc = kstat_open(); - - if( !kc ){ - strcpy(str, "(unknown) "); - return -1; - } - - ks = kstat_lookup( kc, "unix", 0, "system_misc"); - - if( kstat_read( kc, ks, 0) == -1){ - strcpy( str, "( unknown "); - return -1; - } - - kn = kstat_data_lookup( ks, "avenrun_1min" ); - - if( kn ) { - l[0] = loaddouble(kn->value.ui32); - } - - kn = kstat_data_lookup( ks, "avenrun_5min" ); - - if( kn ) { - l[1] = loaddouble(kn->value.ui32); - } - - kn = kstat_data_lookup( ks, "avenrun_15min" ); - - if( kn ) { - l[2] = loaddouble(kn->value.ui32); - } - - if (str) { - - if (l[0] != -1) - sprintf(str, " %.2f %.2f %.2f", l[0], l[1], l[2]); - else - strcpy(str, " (unknown) "); - } - - kstat_close(kc); - return (int)l[0]; -} - -#endif - -#ifdef __linux__ -int -cpuload(char *str) -{ - double l[3] = {-1, -1, -1}; - FILE *fp; - - if ((fp = fopen("/proc/loadavg", "r"))) { - if (fscanf(fp, "%lf %lf %lf", &l[0], &l[1], &l[2]) != 3) - l[0] = -1; - fclose(fp); - } - if (str) { - if (l[0] != -1) - sprintf(str, " %.2f %.2f %.2f", l[0], l[1], l[2]); - else - strcpy(str, " (unknown) "); - } - return (int)l[0]; -} - -double -swapused(int *total, int *used) -{ - double percent = -1; - char buf[101]; - FILE *fp; - - if ((fp = fopen("/proc/meminfo", "r"))) { - while (fgets(buf, 100, fp) && strstr(buf, "SwapTotal:") == NULL); - sscanf(buf, "%*s %d", total); - fgets(buf, 100, fp); - sscanf(buf, "%*s %d", used); - *used = *total - *used; - if (*total != 0) - percent = (double)*used / (double)*total; - fclose(fp); - } - return percent; -} - -#endif diff --git a/mbbsd/othello.c b/mbbsd/othello.c deleted file mode 100644 index 99dd4794..00000000 --- a/mbbsd/othello.c +++ /dev/null @@ -1,577 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#define LOGFILE "etc/othello.log" -#define SECRET "etc/othello.secret" -#define NR_TABLE 2 - -#define true 1 -#define false 0 -#define STARTX 3 -#define STARTY 20 -#define NONE_CHESS " " -#define WHITE_CHESS "¡´" -#define BLACK_CHESS "¡³" -#define HINT_CHESS "¡" -#define NONE 0 -#define HINT 1 -#define BLACK 2 -#define WHITE 3 - -#define INVERT(COLOR) (((COLOR))==WHITE?BLACK:WHITE) - -struct OthelloData { - char nowx, nowy; - char number[2]; - - char pass; - char if_hint; - int think, which_table; - - char nowboard[10][10]; - char evaltable[NR_TABLE + 1][10][10]; -}; - -static const char *CHESS_TYPE[] = {NONE_CHESS, HINT_CHESS, BLACK_CHESS, WHITE_CHESS}; -static const char DIRX[] = {-1, -1, -1, 0, 1, 1, 1, 0}; -static const char DIRY[] = {-1, 0, 1, 1, 1, 0, -1, -1}; -static const char init_table[NR_TABLE + 1][5][5] = { - {{0, 0, 0, 0, 0}, - {0, 30, -3, 2, 2}, - {0, -3, -3, -1, -1}, - {0, 2, -1, 1, 1}, - {0, 2, -1, 1, 0}}, - - {{0, 0, 0, 0, 0}, - {0, 70, 5, 20, 30}, - {0, 5, -5, 3, 3}, - {0, 20, 3, 5, 5}, - {0, 30, 3, 5, 5}}, - - {{0, 0, 0, 0, 0}, - {0, 5, 2, 2, 2}, - {0, 2, 1, 1, 1}, - {0, 2, 1, 1, 1}, - {0, 2, 1, 1, 1}} -}; - -static void -print_chess(struct OthelloData *od, int x, int y, char chess) -{ - move(STARTX - 1 + x * 2, STARTY - 2 + y * 4); - if (chess != HINT || od->if_hint == 1) - outs(CHESS_TYPE[(int)chess]); - else - outs(CHESS_TYPE[NONE]); - refresh(); -} - -static void -printboard(struct OthelloData *od) -{ - int i; - - move(STARTX, STARTY); - outs("¢z¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢{"); - for (i = 0; i < 7; i++) { - move(STARTX + 1 + i * 2, STARTY); - outs("¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x"); - move(STARTX + 2 + i * 2, STARTY); - outs("¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t"); - } - move(STARTX + 1 + i * 2, STARTY); - outs("¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x ¢x"); - move(STARTX + 2 + i * 2, STARTY); - outs("¢|¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢}"); - print_chess(od, 4, 4, WHITE); - print_chess(od, 5, 5, WHITE); - print_chess(od, 4, 5, BLACK); - print_chess(od, 5, 4, BLACK); - move(3, 56); - prints("(¶Â)%s", cuser.userid); - move(3, 72); - outs(": 02"); - move(4, 56); - outs("(¥Õ)¹q¸£ : 02"); - move(6, 56); - outs("¡ ¥i¥H¤U¤§³B"); - move(7, 56); - outs("[q] °h¥X"); - move(8, 56); - outs("[h] ¶}±Ò/Ãö³¬ ´£¥Ü"); - move(9, 56); - outs("[Enter][Space] ¤U´Ñ"); - move(10, 56); - outs("¤W:¡ô, i"); - move(11, 56); - outs("¤U:¡õ, k"); - move(12, 56); - outs("¥ª:¡ö, j"); - move(13, 56); - outs("¥k:¡÷, l"); -} - -static int -get_key(struct OthelloData *od, int x, int y) -{ - int ch; - - move(STARTX - 1 + x * 2, STARTY - 1 + y * 4); - ch = igetch(); - move(STARTX - 1 + x * 2, STARTY - 2 + y * 4); - if (od->nowboard[x][y] != HINT || od->if_hint == 1) - outs(CHESS_TYPE[(int)od->nowboard[x][y]]); - else - outs(CHESS_TYPE[NONE]); - return ch; -} - -static int -eatline(int i, int j, char color, int dir, char chessboard[][10]) -{ - int tmpx, tmpy; - char tmpchess; - - tmpx = i + DIRX[dir]; - tmpy = j + DIRY[dir]; - tmpchess = chessboard[tmpx][tmpy]; - if (tmpchess == -1) - return false; - if (tmpchess != INVERT(color)) - return false; - - tmpx += DIRX[dir]; - tmpy += DIRY[dir]; - tmpchess = chessboard[tmpx][tmpy]; - while (tmpchess != -1) { - if (tmpchess < BLACK) - return false; - if (tmpchess == color) { - while (i != tmpx || j != tmpy) { - chessboard[i][j] = color; - i += DIRX[dir]; - j += DIRY[dir]; - } - return true; - } - tmpx += DIRX[dir]; - tmpy += DIRY[dir]; - tmpchess = chessboard[tmpx][tmpy]; - } - return false; -} - -static int -if_can_put(int x, int y, char color, char chessboard[][10]) -{ - int i, temp, checkx, checky; - - if (chessboard[x][y] < BLACK) - for (i = 0; i < 8; i++) { - checkx = x + DIRX[i]; - checky = y + DIRY[i]; - temp = chessboard[checkx][checky]; - if (temp < BLACK) - continue; - if (temp != color) - while (chessboard[checkx += DIRX[i]][checky += DIRY[i]] > HINT) - if (chessboard[checkx][checky] == color) - return true; - } - return false; -} - -static int -get_hint(struct OthelloData *od, char color) -{ - int i, j, temp = 0; - - for (i = 1; i <= 8; i++) - for (j = 1; j <= 8; j++) { - if (od->nowboard[i][j] == HINT) - od->nowboard[i][j] = NONE; - if (if_can_put(i, j, color, od->nowboard)) { - od->nowboard[i][j] = HINT; - temp++; - } - print_chess(od, i, j, od->nowboard[i][j]); - } - return temp; -} - -static void -eat(int x, int y, int color, char chessboard[][10]) -{ - int k; - - for (k = 0; k < 8; k++) - eatline(x, y, color, k, chessboard); -} - -static void -end_of_game(struct OthelloData *od, int quit) -{ - FILE *fp, *fp1; - char *opponent[] = {"", "CD-65", "", "À¦¨à", "¤p«Ä", "", "¤j¤H", "±M®a"}; - - move(STARTX - 1, 30); - outs(" "); - move(22, 35); - fp = fopen(LOGFILE, "a"); - if (!quit) { - fp1 = fopen(SECRET, "a"); - if (fp1) { - fprintf(fp1, "%d,%d,%s,%02d,%02d\n", od->think, od->which_table, - cuser.userid, od->number[0], od->number[1]); - fclose(fp1); - } - } - if (quit) { - if (od->number[0] == 2 && od->number[1] == 2) { - if (fp) - fclose(fp); - return; - } - fprintf(fp, "¦b%s¯Å¤¤, %sÁ{°}²æ°k\n", opponent[od->think], cuser.userid); - if (fp) - fclose(fp); - return; - } - if (od->number[0] > od->number[1]) { - prints("§AŤF¹q¸£%02d¤l", od->number[0] - od->number[1]); - if (od->think == 6 && od->number[0] - od->number[1] >= 50) - demoney(200); - if (od->think == 7 && od->number[0] - od->number[1] >= 40) - demoney(200); - if (fp) - fprintf(fp, "¦b%s¯Å¤¤, %s¥H %02d:%02d ŤF¹q¸£%02d¤l\n", - opponent[od->think], cuser.userid, od->number[0], od->number[1], - od->number[0] - od->number[1]); - } else if (od->number[1] > od->number[0]) { - prints("¹q¸£Ä¹¤F§A%02d¤l", od->number[1] - od->number[0]); - if (fp) { - fprintf(fp, "¦b%s¯Å¤¤, ", opponent[od->think]); - if (od->number[1] - od->number[0] > 20) - fprintf(fp, "¹q¸£¥H %02d:%02d ºG¹q%s %02d¤l\n", od->number[1], - od->number[0], cuser.userid, od->number[1] - od->number[0]); - else - fprintf(fp, "¹q¸£¥H %02d:%02d ŤF%s %02d¤l\n", od->number[1], - od->number[0], cuser.userid, od->number[1] - od->number[0]); - } - } else { - outs("§A©M¹q¸£¥´¦¨¥¤â!!"); - if (fp) - fprintf(fp, "¦b%s¯Å¤¤, %s©M¹q¸£¥H %02d:%02d ¥´¦¨¤F¥¤â\n", - opponent[od->think], cuser.userid, od->number[1], od->number[0]); - } - if (fp) - fclose(fp); - move(1, 1); - igetch(); -} - -static void -othello_redraw(struct OthelloData *od) -{ - int i, j; - - for (i = 1; i <= 8; i++) - for (j = 1; j <= 8; j++) - print_chess(od, i, j, od->nowboard[i][j]); -} - -static int -player(struct OthelloData *od, char color) -{ - int ch; - - if (get_hint(od, color)) { - while (true) { - ch = get_key(od, od->nowx, od->nowy); - switch (ch) { - case 'J': - case 'j': - case KEY_LEFT: - od->nowy--; - break; - case 'L': - case 'l': - case KEY_RIGHT: - od->nowy++; - break; - case 'I': - case 'i': - case KEY_UP: - od->nowx--; - break; - case 'K': - case 'k': - case KEY_DOWN: - od->nowx++; - break; - case ' ': - case '\r': - if (od->nowboard[(int)od->nowx][(int)od->nowy] != HINT) - break; - od->pass = 0; - od->nowboard[(int)od->nowx][(int)od->nowy] = color; - eat(od->nowx, od->nowy, color, od->nowboard); - print_chess(od, od->nowx, od->nowy, color); - return true; - case 'q': - end_of_game(od, 1); - return false; - case 'H': - case 'h': - od->if_hint = od->if_hint ^ 1; - othello_redraw(od); - break; - } - if (od->nowx == 9) - od->nowx = 1; - if (od->nowx == 0) - od->nowx = 8; - if (od->nowy == 9) - od->nowy = 1; - if (od->nowy == 0) - od->nowy = 8; - } - } else { - od->pass++; - if (od->pass == 1) { - move(23, 34); - outs("§A¥²»Ý©ñ±ó³o¤@¨B!!"); - igetch(); - move(28, 23); - outs(" "); - } else { - end_of_game(od,0); - return false; - } - } - return 0; -} - -static void -init(struct OthelloData *od) -{ - int i, j, i1, j1; - - memset(od, 0, sizeof(struct OthelloData)); - od->nowx = 4; - od->nowy = 4; - od->number[0] = od->number[1] = 2; - for (i = 1; i <= 8; i++) - for (j = 1; j <= 8; j++) { - i1 = 4.5 - abs(4.5 - i); - j1 = 4.5 - abs(4.5 - j); - od->evaltable[0][i][j] = init_table[0][i1][j1]; - od->evaltable[1][i][j] = init_table[1][i1][j1]; - } - memset(od->nowboard, NONE, sizeof(od->nowboard)); - for(i=0;i<10;i++) - od->nowboard[i][0]=od->nowboard[0][i]=od->nowboard[i][9]=od->nowboard[9][i]=-1; - od->nowboard[4][4] = od->nowboard[5][5] = WHITE; - od->nowboard[4][5] = od->nowboard[5][4] = BLACK; -} - -static void -report(struct OthelloData *od) -{ - int i, j; - - od->number[0] = od->number[1] = 0; - for (i = 1; i <= 8; i++) - for (j = 1; j <= 8; j++) - if (od->nowboard[i][j] == BLACK) - od->number[0]++; - else if (od->nowboard[i][j] == WHITE) - od->number[1]++; - move(3, 60); - outs(cuser.userid); - move(3, 72); - prints(": %02d", od->number[0]); - move(4, 60); - prints("¹q¸£ : %02d", od->number[1]); -} - -static int -EVL(struct OthelloData *od, char chessboard[][10], int color, int table_number) -{ - int points = 0, a, b; - for (a = 1; a <= 8; a++) - for (b = 1; b <= 8; b++) - if (chessboard[a][b] > HINT) { - if (chessboard[a][b] == BLACK) - points += od->evaltable[table_number][a][b]; - else - points -= od->evaltable[table_number][a][b]; - } - return ((color == BLACK) ? points : -points); -} - -static int -alphabeta(struct OthelloData *od, int alpha, int beta, int level, char chessboard[][10], - int thinkstep, int color, int table) -{ - int i, j, k, flag = 1; - char tempboard[10][10]; - if (level == thinkstep + 1) - return EVL(od, chessboard, (level & 1 ? color : ((color - 2) ^ 1) + 2), - table); - for (i = 1; i <= 8; i++) { - for (j = 1; j <= 8; j++) { - if (if_can_put(i, j, color, chessboard)) { - flag = 0; - memcpy(tempboard, chessboard, sizeof(char) * 100); - eat(i, j, color, tempboard); - - k = alphabeta(od, alpha, beta, level + 1, tempboard, thinkstep, - ((color - 2) ^ 1) + 2, table); - if (((level & 1) && k > alpha)) - alpha = k; - else if (!(level & 1) && k < beta) - beta = k; - if (alpha >= beta) - break; - } - } - } - if (flag) - return EVL(od, chessboard, color, table); - return ((level & 1) ? alpha : beta); -} - -static int -Computer(struct OthelloData *od, int thinkstep, int table) -{ - int i, j, maxi = 0, maxj = 0, level = 1; - char chessboard[10][10]; - int alpha = -10000, k; - if ((od->number[0] + od->number[1]) > 44) - table = NR_TABLE; - for (i = 1; i <= 8; i++) - for (j = 1; j <= 8; j++) { - if (if_can_put(i, j, WHITE, od->nowboard)) { - memcpy(chessboard, od->nowboard, sizeof(char) * 100); - eat(i, j, WHITE, chessboard); - k = alphabeta(od, alpha, 10000, level + 1, chessboard, thinkstep, - BLACK, table); - if (k > alpha) { - alpha = k; - maxi = i; - maxj = j; - } - } - } - if (alpha != -10000) { - eat(maxi, maxj, WHITE, od->nowboard); - od->pass = 0; - od->nowx = maxi; - od->nowy = maxj; - } else { - move(23, 30); - outs("¹q¸£©ñ±ó³o¤@¨B´Ñ!!"); - od->pass++; - if (od->pass == 2) { - move(23, 24); - outs(" "); - end_of_game(od, 0); - return false; - } - igetch(); - move(23, 24); - outs(" "); - } - return true; -} - -static int -choose(void) -{ - char thinkstep[2]; - - move(2, 0); - outs("½Ð¿ï¾ÜÃø«×:"); - move(5, 0); - outs("[0] Â÷¶}\n"); - outs("(1) CD-65\n");/* ·Q 1 ¨B */ - outs("(2) À¦¨à\n"); /* ·Q 3 ¨B */ - outs("(3) ¤p«Ä\n"); /* ·Q 4 ¨B */ - do { - if (getdata(4, 0, "½Ð¿ï¾Ü¤@Ó¹ï¶H©M±z¹ï¥´:(1~3)", - thinkstep, sizeof(thinkstep), LCECHO) == 0 || - thinkstep[0] == '0') - return 0; - - } while (thinkstep[0] < '1' || thinkstep[0] > '3'); - clear(); - switch (thinkstep[0]) { - case '2': - thinkstep[0] = '3'; - break; - case '3': - thinkstep[0] = '4'; - break; - default: - thinkstep[0] = '1'; - break; - } - return atoi(thinkstep); -} - -#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 - -int -othello_main(void) -{ - struct OthelloData *od; - - lockreturn0(OTHELLO, LOCK_MULTI); - - od=(struct OthelloData*)malloc(sizeof(struct OthelloData)); - if(od==NULL) { - unlockutmpmode(); - return 0; - } - - clear(); - init(od); - od->think = choose(); - if (!od->think) - { - unlockutmpmode(); - free(od); - return 0; - } - showtitle("³æ¤H¶Â¥Õ´Ñ", BBSName); - printboard(od); - od->which_table = random() % NR_TABLE; - while (true) { - move(STARTX - 1, 30); - outs("½ü¨ì§A¤U¤F..."); - if (!player(od, BLACK)) - break; - report(od); - othello_redraw(od); - if (od->number[0] + od->number[1] == 64) { - end_of_game(od, 0); - break; - } - move(STARTX - 1, 30); - outs("¹q¸£«ä¦Ò¤¤..."); - refresh(); - if (!Computer(od, od->think, od->which_table)) - break; - report(od); - othello_redraw(od); - if (od->number[0] + od->number[1] == 64) { - end_of_game(od, 0); - break; - } - } - more(LOGFILE, YEA); - unlockutmpmode(); - free(od); - return 1; -} diff --git a/mbbsd/passwd.c b/mbbsd/passwd.c deleted file mode 100644 index d0dd4015..00000000 --- a/mbbsd/passwd.c +++ /dev/null @@ -1,171 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -static int semid = -1; - -#ifndef SEM_R -#define SEM_R 0400 -#endif - -#ifndef SEM_A -#define SEM_A 0200 -#endif - -#ifndef __FreeBSD__ -#include <sys/sem.h> -union semun { - int val; /* value for SETVAL */ - struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ - unsigned short *array; /* array for GETALL & SETALL */ - struct seminfo *__buf; /* buffer for IPC_INFO */ -}; -#endif - -int -passwd_init(void) -{ - semid = semget(PASSWDSEM_KEY, 1, SEM_R | SEM_A | IPC_CREAT | IPC_EXCL); - if (semid == -1) { - if (errno == EEXIST) { - semid = semget(PASSWDSEM_KEY, 1, SEM_R | SEM_A); - if (semid == -1) { - perror("semget"); - exit(1); - } - } else { - perror("semget"); - exit(1); - } - } else { - union semun s; - - s.val = 1; - if (semctl(semid, 0, SETVAL, s) == -1) { - perror("semctl"); - exit(1); - } - } - - return 0; -} - -int -passwd_update_money(int num) -/* update money only - Ptt: don't call it directly, call deumoney() */ -{ - int pwdfd; - int money=moneyof(num); - userec_t u; - if (num < 1 || num > MAX_USERS) - return -1; - - if ((pwdfd = open(fn_passwd, O_WRONLY)) < 0) - exit(1); - lseek(pwdfd, sizeof(userec_t) * (num - 1) + - ((char *)&u.money - (char *)&u), SEEK_SET); - write(pwdfd, &money, sizeof(int)); - close(pwdfd); - return 0; -} - -void -passwd_force_update(int flag) -{ - if(!currutmp || (currutmp->alerts & ALERT_PWD) == 0) - return; - currutmp->alerts &= ~flag; -} - -int -passwd_update(int num, userec_t * buf) -{ - int pwdfd; - if (num < 1 || num > MAX_USERS) - return -1; - buf->money = moneyof(num); - if(usernum == num && currutmp && ((pwdfd = currutmp->alerts) & ALERT_PWD)) - { - userec_t u; - passwd_query(num, &u); - if(pwdfd & ALERT_PWD_BADPOST) - cuser.badpost = buf->badpost = u.badpost; - if(pwdfd & ALERT_PWD_GOODPOST) - cuser.goodpost = buf->goodpost = u.goodpost; - if(pwdfd & ALERT_PWD_PERM) - cuser.userlevel = buf->userlevel = u.userlevel; - if(pwdfd & ALERT_PWD_JUSTIFY) - { - memcpy(buf->justify, u.justify, sizeof(u.justify)); - memcpy(cuser.justify, u.justify, sizeof(u.justify)); - memcpy(buf->email, u.email, sizeof(u.email)); - memcpy(cuser.email, u.email, sizeof(u.email)); - } - currutmp->alerts &= ~ALERT_PWD; - } - if ((pwdfd = open(fn_passwd, O_WRONLY)) < 0) - exit(1); - lseek(pwdfd, sizeof(userec_t) * (num - 1), SEEK_SET); - write(pwdfd, buf, sizeof(userec_t)); - close(pwdfd); - return 0; -} - -int -passwd_query(int num, userec_t * buf) -{ - int pwdfd; - if (num < 1 || num > MAX_USERS) - return -1; - if ((pwdfd = open(fn_passwd, O_RDONLY)) < 0) - exit(1); - lseek(pwdfd, sizeof(userec_t) * (num - 1), SEEK_SET); - read(pwdfd, buf, sizeof(userec_t)); - close(pwdfd); - return 0; -} - -int initcuser(const char *userid) -{ - // Ptt: setup cuser and usernum here - if(userid[0]=='\0' || - !(usernum = searchuser(userid, NULL)) || usernum > MAX_USERS) - return -1; - passwd_query(usernum, &cuser); - return usernum; -} - -int -passwd_apply(void *ctx, int (*fptr) (void *ctx, int, userec_t *)) -{ - int i; - userec_t user; - for (i = 0; i < MAX_USERS; i++) { - passwd_query(i + 1, &user); - if ((*fptr) (ctx, i, &user) < 0) - return -1; - } - return 0; -} - -void -passwd_lock(void) -{ - struct sembuf buf = {0, -1, SEM_UNDO}; - - if (semop(semid, &buf, 1)) { - perror("semop"); - exit(1); - } -} - -void -passwd_unlock(void) -{ - struct sembuf buf = {0, 1, SEM_UNDO}; - - if (semop(semid, &buf, 1)) { - perror("semop"); - exit(1); - } -} diff --git a/mbbsd/pfterm.c b/mbbsd/pfterm.c deleted file mode 100644 index 65a09a62..00000000 --- a/mbbsd/pfterm.c +++ /dev/null @@ -1,2502 +0,0 @@ -////////////////////////////////////////////////////////////////////////// -// pfterm environment settings -////////////////////////////////////////////////////////////////////////// -#ifdef _PFTERM_TEST_MAIN - -#define USE_PFTERM -#define EXP_PFTERM -#define DBCSAWARE -#define FT_DBCS_NOINTRESC 1 -#define DBG_TEXT_FD - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <assert.h> - -#else - -#define HAVE_GRAYOUT -#include "bbs.h" - -#ifdef DBCS_NOINTRESC -// # ifdef CONVERT -// extern int bbs_convert_type; -// # define FT_DBCS_NOINTRESC ( -// (cuser.uflag & DBCS_NOINTRESC) || -// (bbs_convert_type == CONV_UTF8)) -// # else -# define FT_DBCS_NOINTRESC (cuser.uflag & DBCS_NOINTRESC) -// # endif -#else -# define FT_DBCS_NOINTRESC 0 -#endif - -#endif - -////////////////////////////////////////////////////////////////////////// -// pfterm debug settings -////////////////////////////////////////////////////////////////////////// - -// #define DBG_SHOW_DIRTY -// #define DBG_SHOW_REPRINT // will not work if you enable SHOW_DIRTY. -// #define DBG_DISABLE_OPTMOVE -// #define DBG_DISABLE_REPRINT - -////////////////////////////////////////////////////////////////////////// -// pmore style ansi -// #include "ansi.h" -////////////////////////////////////////////////////////////////////////// - -#ifndef PMORE_STYLE_ANSI -#define ESC_CHR '\x1b' -#define ESC_STR "\x1b" -#define ANSI_COLOR(x) ESC_STR "[" #x "m" -#define ANSI_RESET ESC_STR "[m" -#endif // PMORE_STYLE_ANSI - -#ifndef ANSI_IS_PARAM -#define ANSI_IS_PARAM(c) (c == ';' || (c >= '0' && c <= '9')) -#endif // ANSI_IS_PARAM - -////////////////////////////////////////////////////////////////////////// -// grayout advanced control -// #include "grayout.h" -////////////////////////////////////////////////////////////////////////// -#ifndef GRAYOUT_DARK -#define GRAYOUT_COLORBOLD (-2) -#define GRAYOUT_BOLD (-1) -#define GRAYOUT_DARK (0) -#define GRAYOUT_NORM (1) -#define GRAYOUT_COLORNORM (+2) -#endif // GRAYOUT_DARK - -////////////////////////////////////////////////////////////////////////// -// Typeahead -////////////////////////////////////////////////////////////////////////// -#ifndef TYPEAHEAD_NONE -#define TYPEAHEAD_NONE (-1) -#define TYPEAHEAD_STDIN (0) -#endif // TYPEAHEAD - -////////////////////////////////////////////////////////////////////////// -// pfterm: piaip's flat terminal system, a new replacement for 'screen'. -// pfterm can also be read as "Perfect Term" -// -// piaip's new implementation of terminal system (term/screen) with dirty -// map, designed and optimized for ANSI based output. -// -// "pfterm" is "piaip's flat terminal" or "perfect term", not "PTT's term"!!! -// pfterm is designed for general maple-family BBS systems, not -// specific to any branch. -// -// Author: Hung-Te Lin (piaip), Dec. 2007. -// -// Copyright(c) 2007-2008 Hung-Te Lin <piaip@csie.ntu.edu.tw> -// All Rights Reserved. -// You are free to use, modify, redistribute this program in any -// non-commercial usage (including network service). -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// MAJOR IMPROVEMENTS: -// - Interpret ANSI code and maintain a virtual terminal -// - Dual buffer for dirty map and optimized output -// -// TODO AND DONE: -// - DBCS aware and prevent interrupting DBCS [done] -// - optimization with relative movement [done] -// - optimization with ENTER/clrtoeol [done] -// - ncurses-like API [done] -// - inansistr to output escaped string [done] -// - handle incomplete DBCS characters [done] -// - optimization with reprint ability [done] -// - add auto wrap control -// -// DEPRECATED: -// - standout() [rework getdata() and namecomplete()] -// - talk.c (big_picture) [rework talk.c] -// -////////////////////////////////////////////////////////////////////////// -// Reference: -// http://en.wikipedia.org/wiki/ANSI_escape_code -// http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf -////////////////////////////////////////////////////////////////////////// - -// Experimental now -#if defined(EXP_PFTERM) || defined(USE_PFTERM) - -////////////////////////////////////////////////////////////////////////// -// pfterm Configurations -////////////////////////////////////////////////////////////////////////// - -// Prevent invalid DBCS characters -#define FTCONF_PREVENT_INVALID_DBCS - -// Some terminals use current attribute to erase background -#define FTCONF_CLEAR_SETATTR - -// Some terminals (NetTerm, PacketSite) have bug in bolding attribute. -#define FTCONF_WORKAROUND_BOLD - -// Some terminals prefer VT100 style scrolling, including Win/DOS telnet -#undef FTCONF_USE_ANSI_SCROLL -#undef FTCONF_USE_VT100_SCROLL - -// Few poor terminals do not have relative move (ABCD). -#undef FTCONF_USE_ANSI_RELMOVE - -// Handling ANSI commands with 2 parameters (ex, ESC[m;nH) -// 2: Good terminals can accept any omit format (ESC[;nH) -// 1: Poor terminals (eg, Win/DOS telnet) can only omit 2nd (ESC[mH) -// 0: Very few poor terminals (eg, CrazyTerm/BBMan) cannot omit any parameters -#define FTCONF_ANSICMD2_OMIT (0) - -////////////////////////////////////////////////////////////////////////// -// Flat Terminal Definition -////////////////////////////////////////////////////////////////////////// - -#define FTSZ_DEFAULT_ROW (24) -#define FTSZ_DEFAULT_COL (80) -#define FTSZ_MIN_ROW (24) -#define FTSZ_MAX_ROW (100) -#define FTSZ_MIN_COL (80) -#define FTSZ_MAX_COL (320) - -#define FTCHAR_ERASE (' ') -#define FTATTR_ERASE (0x07) -#define FTCHAR_BLANK (' ') -#define FTATTR_DEFAULT (FTATTR_ERASE) -#define FTCHAR_INVALID_DBCS ('?') -// #define FTATTR_TRANSPARENT (0x80) - -#define FTDIRTY_CHAR (0x01) -#define FTDIRTY_ATTR (0x02) -#define FTDIRTY_DBCS (0x04) -#define FTDIRTY_INVALID_DBCS (0x08) -#define FTDIRTY_RAWMOVE (0x10) - -#define FTDBCS_SAFE (0) // standard DBCS -#define FTDBCS_UNSAFE (1) // not on all systems (better do rawmove) -#define FTDBCS_INVALID (2) // invalid - -#define FTCMD_MAXLEN (63) // max escape command sequence length -#define FTATTR_MINCMD (16) - -#ifndef FTCONF_USE_ANSI_RELMOVE -# define FTMV_COST (8) // always ESC[m;nH will costs avg 8 bytes -#else -# define FTMV_COST (5) // ESC[ABCD with ESC[m;nH costs avg 4+ bytes -#endif - -////////////////////////////////////////////////////////////////////////// -// Flat Terminal Data Type -////////////////////////////////////////////////////////////////////////// - -typedef unsigned char ftchar; // primitive character type -typedef unsigned char ftattr; // primitive attribute type - -////////////////////////////////////////////////////////////////////////// -// Flat Terminal Structure -////////////////////////////////////////////////////////////////////////// - -typedef struct -{ - ftchar **cmap[2]; // character map - ftattr **amap[2]; // attribute map - ftchar *dmap; // dirty map - ftchar *dcmap; // processed display map - ftattr attr; - int rows, cols; - int y, x; - int sy,sx; // stored cursor - int mi; // map index, mi = current map and (1-mi) = old map - int dirty; - int scroll; - - // memory allocation - int mrows, mcols; - - // raw terminal status - int ry, rx; - ftattr rattr; - - // typeahead - char typeahead; - - // escape command - ftchar cmd[FTCMD_MAXLEN+1]; - int szcmd; - -} FlatTerm; - -static FlatTerm ft; - -#ifdef _WIN32 - // sorry, we support only 80x24 on Windows now. - HANDLE hStdout; - COORD coordBufSize = {80, 24}, coordBufCoord = {0, 0}; - SMALL_RECT winrect = {0, 0, 79, 23}; - CHAR_INFO winbuf[80*24]; -#endif - -////////////////////////////////////////////////////////////////////////// -// Flat Terminal Utility Macro -////////////////////////////////////////////////////////////////////////// - -// ftattr: 0| FG(3) | BOLD(1) | BG(3) | BLINK(1) |8 -#define FTATTR_FGSHIFT (0) -#define FTATTR_BGSHIFT (4) -#define FTATTR_GETFG(x) ((x >> FTATTR_FGSHIFT) & 0x7) -#define FTATTR_GETBG(x) ((x >> FTATTR_BGSHIFT) & 0x7) -#define FTATTR_FGMASK ((ftattr)(0x7 << FTATTR_FGSHIFT)) -#define FTATTR_BGMASK ((ftattr)(0x7 << FTATTR_BGSHIFT)) -#define FTATTR_BOLD (0x08) -#define FTATTR_BLINK (0x80) -#define FTATTR_DEFAULT_FG (FTATTR_GETFG(FTATTR_DEFAULT)) -#define FTATTR_DEFAULT_BG (FTATTR_GETBG(FTATTR_DEFAULT)) -#define FTATTR_MAKE(f,b) (((f)<<FTATTR_FGSHIFT)|((b)<<FTATTR_BGSHIFT)) -#define FTCHAR_ISBLANK(x) ((x) == (FTCHAR_BLANK)) - -#define FTCMAP ft.cmap[ft.mi] -#define FTAMAP ft.amap[ft.mi] -#define FTCROW FTCMAP[ft.y] -#define FTAROW FTAMAP[ft.y] -#define FTC FTCROW[ft.x] -#define FTA FTAROW[ft.x] -#define FTD ft.dmap -#define FTDC ft.dcmap -#define FTPC (FTCROW+ft.x) -#define FTPA (FTAROW+ft.x) -#define FTOCMAP ft.cmap[1-ft.mi] -#define FTOAMAP ft.amap[1-ft.mi] - - -// for fast checking, we use reduced range here. -// Big5: LEAD = 0x81-0xFE, TAIL = 0x40-0x7E/0xA1-0xFE -#define FTDBCS_ISLEAD(x) (((unsigned char)(x))>=(0x80)) -#define FTDBCS_ISTAIL(x) (((unsigned char)(x))>=(0x40)) - -// - 0xFF is used as telnet IAC, don't use it! -// - 0x80 is invalid for Big5. -#define FTDBCS_ISBADLEAD(x) ((((unsigned char)(x)) == 0x80) || (((unsigned char)(x)) == 0xFF)) - -// even faster: -// #define FTDBCS_ISLEAD(x) (((unsigned char)(x)) & 0x80) -// #define FTDBCS_ISTAIL(x) (((unsigned char)(x)) & ((unsigned char)~0x3F)) - -#define FTDBCS_ISSBCSPRINT(x) \ - (((unsigned char)(x))>=' ' && ((unsigned char)(x))<0x80) - -#ifndef min -#define min(x,y) (((x)<(y))?(x):(y)) -#endif - -#ifndef max -#define max(x,y) (((x)>(y))?(x):(y)) -#endif - -#ifndef abs -#define abs(x) (((x)>0)?(x):-(x)) -#endif - -#define ranged(x,vmin,vmax) (max(min(x,vmax),vmin)) - - -////////////////////////////////////////////////////////////////////////// -// Flat Terminal API -////////////////////////////////////////////////////////////////////////// - -//// common ncurse-like library interface - -// initialization -void initscr (void); -int resizeterm (int rows, int cols); -int endwin (void); - -// attributes -ftattr attrget (void); -void attrset (ftattr attr); -void attrsetfg (ftattr attr); -void attrsetbg (ftattr attr); - -// cursor -void getyx (int *y, int *x); -void getmaxyx (int *y, int *x); -void move (int y, int x); - -// clear -void clear (void); // clrscr + move(0,0) -void clrtoeol (void); // end of line -void clrtobot (void); -// clear (non-ncurses) -void clrtoln (int ln); // clear down to ln ( excluding ln, as [y,ln) ) -void clrcurln (void); // whole line -void clrtobeg (void); // begin of line -void clrtohome (void); -void clrscr (void); // clear and keep cursor untouched -void clrregion (int r1, int r2); // clear [r1,r2], bi-directional. - -// window control -void newwin (int nlines, int ncols, int y, int x); - -// flushing -void refresh (void); // optimized refresh -void doupdate (void); // optimized refresh, ignore input queue -void redrawwin (void); // invalidate whole screen -int typeahead (int fd);// prevent refresh if input queue is not empty - -// scrolling -void scroll (void); // scroll up -void rscroll (void); // scroll down -void scrl (int rows); - -// output (ncurses flavor) -void addch (unsigned char c); // equivalent to outc() -void addstr (const char *s); // equivalent to outs() -void addnstr (const char *s, int n); - -// output (non-ncurses) -void outc (unsigned char c); -void outs (const char *s); -void outns (const char *s, int n); -void outstr (const char *str); // prepare and print a complete string. -void addstring (const char *str); // ncurses-like of outstr(). - -// readback -int instr (char *str); -int innstr (char *str, int n); // n includes \0 -int inansistr (char *str, int n); // n includes \0 - -// deprecated -void standout (void); -void standend (void); - -// grayout advanced control -void grayout (int y, int end, int level); - -//// flat-term internal processor - -int fterm_inbuf (void); // raw input adapter -void fterm_rawc (int c); // raw output adapter -void fterm_rawnewline(void); // raw output adapter -void fterm_rawflush (void); // raw output adapter -void fterm_raws (const char *s); -void fterm_rawnc (int c, int n); -void fterm_rawnum (int arg); -void fterm_rawcmd (int arg, int defval, char c); -void fterm_rawcmd2 (int arg1, int arg2, int defval, char c); -void fterm_rawattr (ftattr attr); // optimized changing attribute -void fterm_rawclear (void); -void fterm_rawclreol (void); -void fterm_rawhome (void); -void fterm_rawscroll (int dy); -void fterm_rawcursor (void); -void fterm_rawmove (int y, int x); -void fterm_rawmove_opt(int y, int x); -void fterm_rawmove_rel(int dy, int dx); - -int fterm_chattr (char *s, ftattr oa, ftattr na); // size(s) > FTATTR_MINCMD -void fterm_exec (void); // execute ft.cmd -void fterm_flippage (void); -void fterm_dupe2bk (void); -void fterm_markdirty (void); // mark as dirty -int fterm_strdlen (const char *s); // length of string for display -int fterm_prepare_str(int len); - -// DBCS supporting -int fterm_DBCS_Big5(unsigned char c1, unsigned char c2); - -////////////////////////////////////////////////////////////////////////// -// Flat Terminal Implementation -////////////////////////////////////////////////////////////////////////// - -#define fterm_markdirty() { ft.dirty = 1; } - -// initialization - -void -initscr(void) -{ -#ifdef _WIN32 - hStdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleScreenBufferSize(hStdout, coordBufSize); - SetConsoleCursorPosition(hStdout, coordBufCoord); -#endif - - memset(&ft, sizeof(ft), 0); - ft.attr = ft.rattr = FTATTR_DEFAULT; - resizeterm(FTSZ_DEFAULT_ROW, FTSZ_DEFAULT_COL); - - // clear both pages - ft.mi = 0; clrscr(); - ft.mi = 1; clrscr(); - ft.mi = 0; - - // typeahead - ft.typeahead = 1; - - fterm_rawclear(); - move(0, 0); -} - -int -endwin(void) -{ - int r, mi = 0; - - // fterm_rawclear(); - - for (mi = 0; mi < 2; mi++) - { - for (r = 0; r < ft.mrows; r++) - { - free(ft.cmap[mi][r]); - free(ft.amap[mi][r]); - } - } - free(ft.dmap); - free(ft.dcmap); - memset(&ft, sizeof(ft), 0); - return 0; -} - -int -resizeterm(int rows, int cols) -{ - int dirty = 0, mi = 0, i = 0; - - rows = ranged(rows, FTSZ_MIN_ROW, FTSZ_MAX_ROW); - cols = ranged(cols, FTSZ_MIN_COL, FTSZ_MAX_COL); - - // adjust memory only for increasing buffer - if (rows > ft.mrows || cols > ft.mcols) - { - for (mi = 0; mi < 2; mi++) - { - // allocate rows - if (rows > ft.mrows) - { - ft.cmap[mi] = (ftchar**)realloc(ft.cmap[mi], - sizeof(ftchar*) * rows); - ft.amap[mi] = (ftattr**)realloc(ft.amap[mi], - sizeof(ftattr*) * rows); - - // allocate new columns - for (i = ft.mrows; i < rows; i++) - { - ft.cmap[mi][i] = (ftchar*)malloc((cols+1) * sizeof(ftchar)); - ft.amap[mi][i] = (ftattr*)malloc((cols+1) * sizeof(ftattr)); - // zero at end to prevent over-run - ft.cmap[mi][i][cols] = 0; - ft.amap[mi][i][cols] = 0; - } - } - - // resize cols - if (cols > ft.mcols) - { - for (i = 0; i < ft.mrows; i++) - { - ft.cmap[mi][i] = (ftchar*)realloc(ft.cmap[mi][i], - (cols+1) * sizeof(ftchar)); - ft.amap[mi][i] = (ftattr*)realloc(ft.amap[mi][i], - (cols+1) * sizeof(ftattr)); - // zero at end to prevent over-run - ft.cmap[mi][i][cols] = 0; - ft.amap[mi][i][cols] = 0; - } - } else { - // we have to deal one case: - // expand x, shrink x, expand y -> - // now new allocated lines will have small x(col) instead of mcol. - // the solution is to modify mcols here, or change the malloc above - // to max(ft.mcols, cols). - ft.mcols = cols; - } - } - - // adjusts dirty and display map. - // no need to initialize anyway. - if (cols > ft.mcols) - { - ft.dmap = (ftchar*) realloc(ft.dmap, - (cols+1) * sizeof(ftchar)); - ft.dcmap = (ftchar*) realloc(ft.dcmap, - (cols+1) * sizeof(ftchar)); - } - - // do mrows/mcols assignment here, because we had 2 maps running loop above. - if (cols > ft.mcols) ft.mcols = cols; - if (rows > ft.mrows) ft.mrows = rows; - dirty = 1; - } - - // clear new exposed buffer after resized - // because we will redawwin(), so need to change front buffer only. - for (i = ft.rows; i < rows; i++) - { - memset(FTCMAP[i], FTCHAR_ERASE, - (cols) * sizeof(ftchar)); - memset(FTAMAP[i], FTATTR_ERASE, - (cols) * sizeof(ftattr)); - } - if (cols > ft.cols) - { - for (i = 0; i < ft.rows; i++) - { - memset(FTCMAP[i]+ft.cols, FTCHAR_ERASE, - (cols-ft.cols) * sizeof(ftchar)); - memset(FTAMAP[i]+ft.cols, FTATTR_ERASE, - (cols-ft.cols) * sizeof(ftattr)); - } - } - - if (ft.rows != rows || ft.cols != cols) - { - ft.rows = rows; - ft.cols = cols; - redrawwin(); - } - - ft.x = ranged(ft.x, 0, ft.cols-1); - ft.y = ranged(ft.y, 0, ft.rows-1); - - return dirty; -} - -// attributes - -ftattr -attrget(void) -{ - return ft.attr; -} - -void -attrset(ftattr attr) -{ - ft.attr = attr; -} - -void -attrsetfg(ftattr attr) -{ - ft.attr &= (~FTATTR_FGMASK); - ft.attr |= ((attr & FTATTR_FGMASK) << FTATTR_FGSHIFT); -} - -void -attrsetbg(ftattr attr) -{ - ft.attr &= (~FTATTR_BGMASK); - ft.attr |= ((attr & FTATTR_FGMASK) << FTATTR_BGSHIFT); -} - -// clear - -void -clrscr(void) -{ - int r; - for (r = 0; r < ft.rows; r++) - memset(FTCMAP[r], FTCHAR_ERASE, ft.cols * sizeof(ftchar)); - for (r = 0; r < ft.rows; r++) - memset(FTAMAP[r], FTATTR_ERASE, ft.cols * sizeof(ftattr)); - fterm_markdirty(); -} - -void -clear(void) -{ - clrscr(); - move(0,0); -} - -void -clrtoeol(void) -{ - ft.x = ranged(ft.x, 0, ft.cols-1); - ft.y = ranged(ft.y, 0, ft.rows-1); - memset(FTPC, FTCHAR_ERASE, ft.cols - ft.x); - memset(FTPA, FTATTR_ERASE, ft.cols - ft.x); - fterm_markdirty(); -} - -void -clrtobeg(void) -{ - ft.x = ranged(ft.x, 0, ft.cols-1); - ft.y = ranged(ft.y, 0, ft.rows-1); - memset(FTCROW, FTCHAR_ERASE, ft.x+1); - memset(FTAROW, FTATTR_ERASE, ft.x+1); - fterm_markdirty(); -} - -void -clrcurrline(void) -{ - ft.y = ranged(ft.y, 0, ft.rows-1); - memset(FTCROW, FTCHAR_ERASE, ft.cols); - memset(FTAROW, FTATTR_ERASE, ft.cols); - fterm_markdirty(); -} - -void -clrtoln(int line) -{ - if (line <= ft.y) - return; - clrregion(ft.y, line-1); -} - -void -clrregion(int r1, int r2) -{ - // bi-direction - if (r1 > r2) - { - int r = r1; - r1 = r2; r2 = r; - } - - // check r1, r2 range - r1 = ranged(r1, 0, ft.rows-1); - r2 = ranged(r2, 0, ft.rows-1); - - for (; r1 <= r2; r1++) - { - memset(FTCMAP[r1], FTCHAR_ERASE, ft.cols); - memset(FTAMAP[r1], FTATTR_ERASE, ft.cols); - } - fterm_markdirty(); -} - -void -clrtobot(void) -{ - clrtoeol(); - clrregion(ft.y+1, ft.rows-1); -} - -void -clrtohome(void) -{ - clrtobeg(); - clrregion(ft.y-1, 0); -} - -void newwin (int nlines, int ncols, int y, int x) -{ - int oy, ox; - // check range - - x = ranged(x, 0, ft.cols-1); - y = ranged(y, 0, ft.rows-1); - ncols = ranged(x+ncols-1, x, ft.cols-1); - nlines = ranged(y+nlines-1, y, ft.rows-1); - ncols = ncols - x + 1; - nlines= nlines- y + 1; - - if (nlines <= 0 || ncols <= 0) - return; - getyx(&oy, &ox); - - while (nlines-- > 0) - { - move(y++, x); - // use prepare_str to erase character - fterm_prepare_str(ncols); - // memset(FTAMAP[y]+x, ft.attr, ncols); - // memset(FTCMAP[y]+x, FTCHAR_ERASE, ncols); - } - move(oy, ox); -} - -// dirty and flushing - -void -redrawwin(void) -{ - // flip page - fterm_flippage(); - clrscr(); - - // clear raw terminal - fterm_rawclear(); - - // flip page again - fterm_flippage(); - - // mark for refresh. - fterm_markdirty(); -} - -int -typeahead(int fd) -{ - switch(fd) - { - case TYPEAHEAD_NONE: - ft.typeahead = 0; - break; - case TYPEAHEAD_STDIN: - ft.typeahead = 1; - break; - default: // shall never reach here - assert(NULL); - break; - } - return 0; -} - -void -refresh(void) -{ - // prevent passive update - if(fterm_inbuf() && ft.typeahead) - return; - doupdate(); -} - -void -doupdate(void) -{ - int y, x; - char touched = 0; - - if (!ft.dirty) - { - fterm_rawcursor(); - return; - } - -#ifdef _WIN32 - - assert(ft.rows == coordBufSize.Y); - assert(ft.cols == coordBufSize.X); - - for (y = 0; y < ft.rows; y++) - { - for (x = 0; x < ft.cols; x++) - { - WORD xAttr = FTAMAP[y][x], xxAttr; - // w32 attribute: bit swap (0,2) and (4, 6) - xxAttr = xAttr & 0xAA; - if (xAttr & 0x01) xxAttr |= 0x04; - if (xAttr & 0x04) xxAttr |= 0x01; - if (xAttr & 0x10) xxAttr |= 0x40; - if (xAttr & 0x40) xxAttr |= 0x10; - - winbuf[y*ft.cols + x].Attributes= xxAttr; - winbuf[y*ft.cols + x].Char.AsciiChar = FTCMAP[y][x]; - } - } - WriteConsoleOutputA(hStdout, winbuf, coordBufSize, coordBufCoord, &winrect); - -#else // !_WIN32 - - // if scroll, do it first - if (ft.scroll) - fterm_rawscroll(ft.scroll); - - // calculate and optimize dirty - for (y = 0; y < ft.rows; y++) - { - int len = ft.cols, ds = 0, derase = 0; - char dbcs = 0, odbcs = 0; // 0: none, 1: lead, 2: tail - - // reset dirty and display map - memset(FTD, 0, ft.cols * sizeof(ftchar)); - memcpy(FTDC,FTCMAP[y], ft.cols * sizeof(ftchar)); - - // first run: character diff - for (x = 0; x < len; x++) - { - // build base dirty information - if (FTCMAP[y][x] != FTOCMAP[y][x]) - FTD[x] |= FTDIRTY_CHAR, ds++; - if (FTAMAP[y][x] != FTOAMAP[y][x]) - FTD[x] |= FTDIRTY_ATTR, ds++; - - // determine DBCS status - if (dbcs == 1) - { -#ifdef FTCONF_PREVENT_INVALID_DBCS - switch(fterm_DBCS_Big5(FTCMAP[y][x-1], FTCMAP[y][x])) - { - case FTDBCS_SAFE: - // safe to print - FTD[x-1] &= ~FTDIRTY_INVALID_DBCS; - FTDC[x-1] = FTCMAP[y][x-1]; - break; - - case FTDBCS_UNSAFE: - // ok to print, but need to rawmove. - FTD[x-1] &= ~FTDIRTY_INVALID_DBCS; - FTDC[x-1] = FTCMAP[y][x-1]; - FTD[x-1] |= FTDIRTY_CHAR; - FTD[x] |= FTDIRTY_RAWMOVE; - break; - - case FTDBCS_INVALID: - // only SBCS safe characters can be print. - if (!FTDBCS_ISSBCSPRINT(FTCMAP[y][x])) - { - FTD[x] |= FTDIRTY_INVALID_DBCS; - FTDC[x] = FTCHAR_INVALID_DBCS; - } - break; - } -#endif // FTCONF_PREVENT_INVALID_DBCS - - dbcs = 2; - // TAIL: dirty prev and me if any is dirty. - if (FTD[x] || FTD[x-1]) - { - FTD[x] |= FTDIRTY_DBCS; - FTD[x-1]|= FTDIRTY_CHAR; - } - } - else if (FTDBCS_ISLEAD(FTCMAP[y][x])) - { - // LEAD: clear dirty when tail was found. - dbcs = 1; -#ifdef FTCONF_PREVENT_INVALID_DBCS - FTD[x] |= FTDIRTY_INVALID_DBCS; - FTDC[x] = FTCHAR_INVALID_DBCS; -#endif // FTCONF_PREVENT_INVALID_DBCS - } - else - { - // NON-DBCS - dbcs = 0; - } - - if (odbcs == 1) - { - // TAIL: dirty prev and me if any is dirty. - odbcs = 2; - if (FTD[x] || FTD[x-1]) - { - FTD[x] |= FTDIRTY_CHAR; - FTD[x-1]|= FTDIRTY_CHAR; - } - } - else if (FTDBCS_ISLEAD(FTOCMAP[y][x])) - { - // LEAD: dirty next? - odbcs = 1; - } - else - { - odbcs = 0; - } - } - -#ifndef DBG_SHOW_DIRTY - if (!ds) - continue; -#endif // DBG_SHOW_DIRTY - - // Optimization: calculate ERASE section - // TODO ERASE takes 3 bytes (ESC [ K), so enable only if derase >= 3? - // TODO ERASE then print can avoid lots of space, optimize in future. - for (x = ft.cols - 1; x >= 0; x--) - if (FTCMAP[y][x] != FTCHAR_ERASE || - FTAMAP[y][x] != FTATTR_ERASE) - break; - else if (FTD[x]) - derase++; - - len = x+1; - - for (x = 0; x < len; x++) - { -#ifndef DBG_SHOW_DIRTY - if (!FTD[x]) - continue; -#endif // !DBG_SHOW_DIRTY - - // Optimization: re-print or move? -#ifndef DBG_DISABLE_REPRINT - while (ft.ry == y && x > ft.rx && abs(x-ft.rx) < FTMV_COST) - { - int i; - // Special case: we may be in position of DBCS tail... - // Inside a refresh() loop, this will never happen. - // However it may occur for the first print entering refresh. - // So enable only space if this is the first run (!touched). - - // if we don't need to change attributes, - // just print remaining characters - for (i = ft.rx; i < x; i++) - { - // if same attribute, simply accept. - if (FTAMAP[y][i] == ft.rattr && touched) - continue; - // XXX spaces may accept (BG=rBG), - // but that will also change cached attribute. - if (!FTCHAR_ISBLANK(FTCMAP[y][i])) - break; - if (FTATTR_GETBG(FTAMAP[y][i]) != FTATTR_GETBG(ft.rattr)) - break; - } - if (i != x) - break; - - // safe to print all! - // printf("[re-print %d chars]", i-ft.rx); - -#ifdef DBG_SHOW_REPRINT - // reverse to hint this is a re-print - fterm_rawattr(FTATTR_MAKE(0, 7) | FTATTR_BOLD); -#endif // DBG_SHOW_REPRINT - - for (i = ft.rx; i < x; i++) - { - fterm_rawc(FTDC[i]); - FTAMAP[y][i] = FTOAMAP[y][i]; // spaces may change attr... - ft.rx++; - } - - break; - } -#endif // !DBG_DISABLE_REPRINT - - if (y != ft.ry || x != ft.rx) - fterm_rawmove_opt(y, x); - -#ifdef DBCSAWARE - if ((FTD[x] & FTDIRTY_DBCS) && (FT_DBCS_NOINTRESC)) - { - // prevent changing attributes inside DBCS - } - else -#endif // DBCSAWARE -#ifdef DBG_SHOW_DIRTY - fterm_rawattr(FTD[x] ? - (FTAMAP[y][x] | FTATTR_BOLD) : (FTAMAP[y][x] & ~FTATTR_BOLD)); -#else // !DBG_SHOW_DIRTY - fterm_rawattr(FTAMAP[y][x]); -#endif // !DBG_SHOW_DIRTY - - fterm_rawc(FTDC[x]); - ft.rx++; - touched = 1; - - if (FTD[x] & FTDIRTY_RAWMOVE) - { - fterm_rawcmd2(ft.ry+1, ft.rx+1, 1, 'H'); - } - } - - if (derase) - { - fterm_rawmove_opt(y, len); - fterm_rawclreol(); - } - } - -#endif // !_WIN32 - - // doing fterm_rawcursor() earlier to enable max display time - fterm_rawcursor(); - fterm_dupe2bk(); - ft.dirty = 0; -} - -// cursor management - -void -getyx(int *y, int *x) -{ - if (y) - *y = ft.y; - if (x) - *x = ft.x; -} - -void -getmaxyx(int *y, int *x) -{ - if (y) - *y = ft.rows; - if (x) - *x = ft.cols; -} - -void -move(int y, int x) -{ - ft.y = ranged(y, 0, ft.rows-1); - ft.x = ranged(x, 0, ft.cols-1); -} - -// scrolling - -void -scrl(int rows) -{ - if (!rows) - return; - if (rows > 0) - { - for (; rows > 0; rows--) - scroll(); - } else { - for (; rows < 0; rows++) - rscroll(); - } -} - -void -scroll() -{ - // scroll up - int y; - ftchar *c0 = FTCMAP[0], *oc0 = FTOCMAP[0]; - ftattr *a0 = FTAMAP[0], *oa0 = FTOAMAP[0]; - - // prevent mixing buffered scroll up+down - if (ft.scroll < 0) - fterm_rawscroll(ft.scroll); - - // smart scroll: move pointers - for (y = 0; y < ft.rows-1; y++) - { - FTCMAP[y] = FTCMAP[y+1]; - FTAMAP[y] = FTAMAP[y+1]; - FTOCMAP[y]= FTOCMAP[y+1]; - FTOAMAP[y]= FTOAMAP[y+1]; - } - FTCMAP[y] = c0; - FTAMAP[y] = a0; - FTOCMAP[y]= oc0; - FTOAMAP[y]= oa0; - - // XXX also clear backup buffer - // must carefully consider if up then down scrolling. - fterm_flippage(); - clrregion(ft.rows-1, ft.rows-1); - fterm_flippage(); - clrregion(ft.rows-1, ft.rows-1); - - ft.scroll ++; - // fterm_markdirty(); // should be already dirty -} - -void -rscroll() -{ - // scroll down - int y; - ftchar *c0 = FTCMAP[ft.rows -1], *oc0 = FTOCMAP[ft.rows -1]; - ftattr *a0 = FTAMAP[ft.rows -1], *oa0 = FTOAMAP[ft.rows -1]; - - // prevent mixing buffered scroll up+down - if (ft.scroll > 0) - fterm_rawscroll(ft.scroll); - - // smart scroll: move pointers - for (y = ft.rows -1; y > 0; y--) - { - FTCMAP[y] = FTCMAP[y-1]; - FTAMAP[y] = FTAMAP[y-1]; - FTOCMAP[y]= FTOCMAP[y-1]; - FTOAMAP[y]= FTOAMAP[y-1]; - } - FTCMAP[y] = c0; - FTAMAP[y] = a0; - FTOCMAP[y]= oc0; - FTOAMAP[y]= oa0; - - // XXX also clear backup buffer - // must carefully consider if up then down scrolling. - fterm_flippage(); - clrregion(0, 0); - fterm_flippage(); - clrregion(0, 0); - - ft.scroll --; - // fterm_markdirty(); // should be already dirty -} - -// output - -void -addch (unsigned char c) -{ - outc(c); -} - -void -addstr (const char *s) -{ - outs(s); -} - -void -addnstr(const char *s, int n) -{ - outns(s, n); -} - -void -addstring(const char *s) -{ - outstr(s); -} - -void -outs(const char *s) -{ - if (!s) - return; - while (*s) - outc(*s++); -} - -void -outns(const char *s, int n) -{ - if (!s) - return; - while (*s && n-- > 0) - outc(*s++); -} - -void -outstr(const char *str) -{ - if (!str) - { - fterm_prepare_str(0); - return; - } - - // calculate real length of str (stripping escapes) - // TODO only print by the returned size - - fterm_prepare_str(fterm_strdlen(str)); - - outs(str); - - // maybe the source string itself is broken... - // basically this check should be done by clients, not term library. -#if 0 - { - int isdbcs = 0; - while (*str) - { - if (isdbcs == 1) isdbcs = 2; - else if (FTDBCS_ISLEAD(*str)) isdbcs = 1; - else isdbcs = 0; - str++; - } - - if (isdbcs == 1) // incomplete string! - outs("\b?"); - } -#endif -} - -void -outc(unsigned char c) -{ - // 0xFF is invalid for most cases (even DBCS), - if (c == 0xFF || c == 0x00) - return; - - fterm_markdirty(); - if (ft.szcmd) - { - // collecting commands - ft.cmd[ft.szcmd++] = c; - - if ((ft.szcmd == 2 && c == '[') || - (ANSI_IS_PARAM(c) && ft.szcmd < FTCMD_MAXLEN)) - return; - - // process as command - fterm_exec(); - ft.szcmd = 0; - } - else if (c == ESC_CHR) - { - // start of escaped commands - ft.cmd[ft.szcmd++] = c; - } - else if (c == '\t') - { - // tab: move by 8, and erase the moved range - int x = ft.x; - if (x % 8 == 0) - x += 8; - else - x += (8-(x%8)); - x = ranged(x, 0, ft.cols-1); - // erase the characters between - if (x > ft.x) - { - memset(FTCROW+ft.x, FTCHAR_ERASE, x - ft.x); - memset(FTAROW+ft.x, ft.attr, x-ft.x); - } - ft.x = x; - } - else if (c == '\b') - { - ft.x = ranged(ft.x-1, 0, ft.cols-1); - } - else if (c == '\r' || c == '\n') - { - // new line: cursor movement, and do not print anything - // XXX old screen.c also calls clrtoeol() for newlins. - clrtoeol(); - ft.x = 0; - ft.y ++; - while (ft.y >= ft.rows) - { - // XXX scroll at next dirty? - // screen.c ignored such scroll. - // scroll(); - ft.y --; - } - } - else if (iscntrl((unsigned char)c)) - { - // unknown control characters: ignore - } - else // normal characters - { - assert (ft.x >= 0 && ft.x < ft.cols); - - // normal characters - FTC = c; -#ifdef FTATTR_TRANSPARENT - if (ft.attr != FTATTR_TRANSPARENT) -#endif // FTATTR_TRANSPARENT - FTA = ft.attr; - - ft.x++; - // XXX allow x == ft.cols? - if (ft.x >= ft.cols) - { - ft.x = 0; - ft.y ++; - while (ft.y >= ft.rows) - { - // XXX scroll at next dirty? - // screen.c ignored such scroll. - // scroll(); - ft.y --; - } - } - } -} - -// readback -int -instr (char *str) -{ - int x = ft.cols -1; - *str = 0; - if (ft.y < 0 || ft.y >= ft.rows || ft.x < 0 || ft.x >= ft.cols) - return 0; - - // determine stopping location - while (x >= ft.x && FTCROW[x] == FTCHAR_ERASE) - x--; - if (x < ft.x) return 0; - x = x - ft.x + 1; - memcpy(str, FTCROW+ft.x, x); - str[x] = 0; - return x; -} - -int -innstr (char *str, int n) -{ - int on = n; - int x = ranged(ft.x + n-1, 0, ft.cols-1); - *str = 0; - n = x - ft.x+1; - if (on < 1 || ft.y < 0 || ft.y >= ft.rows || ft.x < 0 || ft.x >= ft.cols) - return 0; - - // determine stopping location - while (x >= ft.x && FTCROW[x] == FTCHAR_ERASE) - x--; - if (x < ft.x) return 0; - n = x - ft.x + 1; - if (n >= on) n = on-1; - memcpy(str, FTCROW+ft.x, n); - str[n] = 0; - return n; -} - -int -inansistr (char *str, int n) -{ - int x = ft.cols -1, i = 0, szTrail = 0; - char *ostr = str; - char cmd[FTATTR_MINCMD*2] = ""; - - ftattr a = FTATTR_DEFAULT; - *str = 0; - if (ft.y < 0 || ft.y >= ft.rows || ft.x < 0 || ft.x >= ft.cols) - return 0; - - if (n < 1) - return 0; - n--; // preserve last zero - - // determine stopping location - while (x >= ft.x && FTCROW[x] == FTCHAR_ERASE && FTAROW[x] == FTATTR_ERASE) - x--; - - // retrieve [rt.x, x] - if (x < ft.x) return 0; - - // preserve some bytes if last attribute is not FTATTR_DEFAULT - for (i = ft.x; n > szTrail && i <= x; i++) - { - *str = 0; - - if (a != FTAROW[i]) - { - fterm_chattr(cmd, a, FTAROW[i]); - a = FTAROW[i]; - - if (a != FTATTR_DEFAULT) - szTrail = 3; // ESC [ m - else - szTrail = 0; - - if (strlen(cmd) >= n-szTrail) - break; - - strcpy(str, cmd); - n -= strlen(cmd); - str += strlen(cmd); - } - - // n should > szTrail - *str ++ = FTCROW[i]; - n--; - } - - if (szTrail && n >= szTrail) - { - *str++ = ESC_CHR; *str++ = '['; *str++ = 'm'; - } - - *str = 0; - return (str - ostr); -} - -// internal core of piaip's flat-term - -void -fterm_flippage (void) -{ - // we have only 2 pages now. - ft.mi = 1 - ft.mi; -} - -#ifndef fterm_markdirty -void -fterm_markdirty (void) -{ - ft.dirty = 1; -} -#endif - -void fterm_dupe2bk(void) -{ - int r = 0; - - for (r = 0; r < ft.rows; r++) - { - memcpy(FTOCMAP[r], FTCMAP[r], ft.cols * sizeof(ftchar)); - memcpy(FTOAMAP[r], FTAMAP[r], ft.cols * sizeof(ftattr)); - } -} - -int -fterm_DBCS_Big5(unsigned char c1, unsigned char c2) -{ - // ref: http://www.cns11643.gov.tw/web/word/big5/index.html - // High byte: 0xA1-0xFE, 0x8E-0xA0, 0x81-0x8D - // Low byte: 0x40-0x7E, 0xA1-0xFE - // C1: 0x80-0x9F - if (FTDBCS_ISBADLEAD(c1)) - return FTDBCS_INVALID; - if (!FTDBCS_ISTAIL(c2)) - return FTDBCS_INVALID; - if (c1 >= 0x80 && c1 <= 0x9F) - return FTDBCS_UNSAFE; - return FTDBCS_SAFE; -} - -int -fterm_prepare_str(int len) -{ - // clear and make (cursor, +len) as DBCS-ready. - int x = ranged(ft.x, 0, ft.cols-1); - int y = ranged(ft.y, 0, ft.rows-1); - int dbcs = 0, sdbcs = 0; - - // TODO what if x+len is outside range? - - // check if (x,y) is in valid range - if (x != ft.x || y != ft.y) - return -1; - - len = ranged(x+len, x, ft.cols); - - for (x = 0; x < len; x++) - { - // determine DBCS status - if (dbcs == 1) - dbcs = 2; // TAIL - else if (FTDBCS_ISLEAD(FTCROW[x])) - dbcs = 1; // LEAD - else - dbcs = 0; - if (x == ft.x) sdbcs = dbcs; - } - - x = ft.x; - // fix start and end - if(sdbcs == 2 && x > 0) // TAIL, remove word - x--; - if (dbcs == 1 && len < ft.cols) // LEAD, remove word - len ++; - len = ranged(len, 0, ft.cols); - len -= x; - if (len < 0) len = 0; - - memset(FTCROW + x, FTCHAR_ERASE, len); - memset(FTAROW + x, ft.attr, len); - return len; -} - - -void -fterm_exec(void) -{ - ftchar cmd = ft.cmd[ft.szcmd-1]; - char *p = (char*)ft.cmd + 2; // ESC [ - int n = -1, x = -1, y; - - ft.cmd[ft.szcmd] = 0; - - if (isdigit(*p)) - { - n = atoi(p); - - while (*p && isdigit(*p)) - p++; - - if (*p == ';') - p++; - // p points to next param now - } - - switch(cmd) - { - // Cursor Movement - - case 'A': // CUU: CSI n A - case 'B': // CUD: CSI n B - case 'C': // CUF: CSI n C - case 'D': // CUB: CSI n D - // Moves the cursor n (default 1) cells in the given direction. - // If the cursor is already at the edge of the screen, this has no effect. - if (n < 1) - n = 1; - getyx(&y, &x); - if (cmd == 'A') { y -= n; } - else if (cmd == 'B') { y += n; } - else if (cmd == 'C') { x += n; } - else if (cmd == 'D') { x -= n; } - move(y, x); - break; - - case 'E': // CNL: CSI n E - case 'F': // CPL: CSI n F - // Moves cursor to beginning of the line - // n (default 1) lines up/down (next/previous line). - if (n < 1) - n = 1; - getyx(&y, &x); - if (cmd == 'E') { y -= n; } - else if (cmd == 'F') { y += n; } - move(y, 0); - break; - - case 'G': // CHA: CSI n G - // Moves the cursor to column n. - if (n < 1) - n = 1; - getyx(&y, &x); - move(y, n-1); - break; - - case 'H': // CUP: CSI n ; m H - case 'f': // HVP: CSI n ; m f - // Moves the cursor to row n, column m. - // The values are 1-based, and default to 1 (top left corner) if omitted. - // A sequence such as CSI ;5H is a synonym for CSI 1;5H as well as - // CSI 17;H is the same as CSI 17H and CSI 17;1H - y = n; - if (y >= 0 && isdigit(*p)) - x = atoi((char*)p); - if (y < 0) y = 1; - if (x < 0) x = 1; - move(y-1, x-1); - break; - - // Clear - - case 'J': // ED: CSI n J - // Clears part of the screen. - // If n is zero (or missing), clear from cursor to end of screen. - // If n is one, clear from cursor to beginning of the screen. - // If n is two, clear entire screen - if (n == 0 || n < 0) - clrtobot(); - else if (n == 1) - clrtohome(); - else if (n == 2) - { - clrregion(0, ft.rows-1); - } - break; - - case 'K': // EL: CSI n K - // Erases part of the line. - // If n is zero (or missing), clear from cursor to the end of the line. - // If n is one, clear from cursor to beginning of the line. - // If n is two, clear entire line. Cursor position does not change. - if (n == 0 || n < 0) - clrtoeol(); - else if (n == 1) - clrtobeg(); - else if (n == 2) - clrcurrline(); - break; - - case 's': // SCP: CSI s - // Saves the cursor position. - getyx(&ft.sy, &ft.sx); - break; - - case 'u': // RCP: CSI u - // Restores the cursor position. - move(ft.sy, ft.sx); - break; - - case 'S': // SU: CSI n S - // Scroll whole page up by n (default 1) lines. - // New lines are added at the bottom. - if (n < 1) - n = 1; - scrl(n); - break; - - case 'T': // SD: CSI n T - // Scroll whole page down by n (default 1) lines. - // New lines are added at the top. - if (n < 1) - n = 1; - scrl(-n); - break; - - case 'm': // SGR: CSI n [;k] m - // Sets SGR (Select Graphic Rendition) parameters. - // After CSI can be zero or more parameters separated with ;. - // With no parameters, CSI m is treated as CSI 0 m (reset / normal), - // which is typical of most of the ANSI codes. - // --------------------------------------------------------- - // SGR implementation: - // SGR 0 (reset/normal) is supported. - // SGR 1 (intensity: bold) is supported. - // SGR 2 (intensity: faint) is not supported. - // SGR 3 (italic: on) is not supported. (converted to inverse?) - // SGR 4 (underline: single) is not supported. - // SGR 5 (blink: slow) is supported. - // SGR 6 (blink: rapid) is converted to (blink: slow) - // SGR 7 (image: negative) is partially supported (not a really attribute). - // SGR 8 (conceal) is not supported. - // SGR 21(underline: double) is not supported. - // SGR 22(intensity: normal) is supported. - // SGR 24(underline: none) is not supported. - // SGR 25(blink: off) is supported. - // SGR 27(image: positive) is not supported. - // SGR 28(reveal) is not supported. - // SGR 30-37 (FG) is supported. - // SGR 39 (FG-reset) is supported. - // SGR 40-47 (BG) is supported. - // SGR 49 (BG-reset) is supported. - if (n == -1) // first param - n = 0; - while (n > -1) - { - if (n >= 30 && n <= 37) - { - // set foreground - attrsetfg(n - 30); - } - else if (n >= 40 && n <= 47) - { - // set background - attrsetbg(n - 40); - } - else switch(n) - { - case 0: - attrset(FTATTR_DEFAULT); - break; - case 1: - attrset(attrget() | FTATTR_BOLD); - break; - case 22: - attrset(attrget() & ~FTATTR_BOLD); - break; - case 5: - case 6: - attrset(attrget() | FTATTR_BLINK); - break; - case 25: - attrset(attrget() & ~FTATTR_BLINK); - break; - case 3: - case 7: - { - ftattr a = attrget(); - attrsetfg(FTATTR_GETBG(a)); - attrsetbg(FTATTR_GETFG(a)); - } - break; - case 39: - attrsetfg(FTATTR_DEFAULT_FG); - break; - case 49: - attrsetbg(FTATTR_DEFAULT_BG); - break; - } - - // parse next command - n = -1; - if (*p == ';') - { - n = 0; - p++; - } - else if (isdigit(*p)) - { - n = atoi(p); - while (isdigit(*p)) p++; - if (*p == ';') - p++; - } - } - break; - - default: // unknown command. - break; - } -} - -int -fterm_chattr(char *s, ftattr oattr, ftattr nattr) -{ - ftattr - fg, bg, bold, blink, - ofg, obg, obold, oblink; - char lead = 1; - - if (oattr == nattr) - return 0; - - *s++ = ESC_CHR; - *s++ = '['; - - // optimization: reset as default - if (nattr == FTATTR_DEFAULT) - { - *s++ = 'm'; - *s++ = 0; - return 1; - } - - fg = FTATTR_GETFG(nattr); - bg = FTATTR_GETBG(nattr); - bold = (nattr & FTATTR_BOLD) ? 1 : 0; - blink = (nattr & FTATTR_BLINK)? 1 : 0; - - ofg = FTATTR_GETFG(oattr); - obg = FTATTR_GETBG(oattr); - obold = (oattr & FTATTR_BOLD) ? 1 : 0; - oblink = (oattr & FTATTR_BLINK)? 1 : 0; - - // we dont use "disable blink/bold" commands, - // so if these settings are changed then we must reset. - // another case is changing background to default background - - // better use "RESET" to override it. - // Same for foreground. - // Possible optimization: when blink/bold on, don't RESET - // for background change? - if ((oblink != blink && !blink) || - (obold != bold && !bold) || - (bg == FTATTR_DEFAULT_BG && obg != bg) || - (fg == FTATTR_DEFAULT_FG && ofg != fg) ) - { - if (lead) lead = 0; else *s++ = ';'; - *s++ = '0'; - - ofg = FTATTR_DEFAULT_FG; - obg = FTATTR_DEFAULT_BG; - obold = 0; oblink = 0; - } - - if (bold && !obold) - { - if (lead) lead = 0; else *s++ = ';'; - *s++ = '1'; - -#ifdef FTCONF_WORKAROUND_BOLD - // Issue here: - // PacketSite does not understand ESC[1m. It needs ESC[1;37m - // NetTerm defaults bold color to yellow. - // As a result, we use ESC[1;37m for the case. - if (fg == FTATTR_DEFAULT_FG) - ofg = ~ofg; -#endif // FTCONF_WORKAROUND_BOLD - - } - if (blink && !oblink) - { - if (lead) lead = 0; else *s++ = ';'; - *s++ = '5'; // XXX 5(slow) or 6(fast)? - } - if (ofg != fg) - { - if (lead) lead = 0; else *s++ = ';'; - *s++ = '3'; - *s++ = '0' + fg; - } - if (obg != bg) - { - if (lead) lead = 0; else *s++ = ';'; - *s++ = '4'; - *s++ = '0' + bg; - } - *s++ = 'm'; - *s++ = 0; - return 1; -} - -int -fterm_strdlen(const char *s) -{ - char ansi = 0; - int sz = 0; - - // the logic should match outc(). - - while (s && *s) - { - if (!ansi) // ansi == 0 - { - switch(*s) - { - case ESC_CHR: - ansi++; - break; - - case '\r': - case '\n': - break; - - case '\b': - if (sz) sz--; - break; - - case '\t': - // XXX how to deal with this? - sz ++; - break; - - default: - if (!iscntrl((unsigned char)*s)) - sz++; - break; - } - } - else if (ansi == 1) - { - if (*s == '[') - ansi++; - else - ansi = 0; - } - else if (!ANSI_IS_PARAM(*s)) // ansi == 2 - { - // TODO outc() take max to FTCMD_MAXLEN now... - ansi = 0; - } - s++; - } - return sz; -} - -void -fterm_rawattr(ftattr rattr) -{ - static char cmd[FTATTR_MINCMD*2]; - if (!fterm_chattr(cmd, ft.rattr, rattr)) - return; - - fterm_raws(cmd); - ft.rattr = rattr; -} - -void -fterm_rawnum(int arg) -{ - if (arg < 0 || arg > 99) - { - // complex. use printf. - char sarg[16]; // max int - sprintf(sarg, "%d", arg); - fterm_raws(sarg); - } else if (arg < 10) { - // 0 .. 10 - fterm_rawc('0' + arg); - } else { - fterm_rawc('0' + arg/10); - fterm_rawc('0' + arg%10); - } -} -void -fterm_rawcmd(int arg, int defval, char c) -{ - fterm_rawc(ESC_CHR); - fterm_rawc('['); - if (arg != defval) - fterm_rawnum(arg); - fterm_rawc(c); -} - -void -fterm_rawcmd2(int arg1, int arg2, int defval, char c) -{ - fterm_rawc(ESC_CHR); - fterm_rawc('['); - - // See FTCONF_ANSICMD2_OMIT - // XXX Win/DOS telnet does now accept omitting first value - // ESC[nX and ESC[n;X works, but ESC[;mX does not work. - if (arg1 != defval || arg2 != defval) - { -#if (FTCONF_ANSICMD2_OMIT >= 2) - if (arg1 != defval) -#endif - fterm_rawnum(arg1); - -#if (FTCONF_ANSICMD2_OMIT >= 1) - if (arg2 != defval) -#endif - { - fterm_rawc(';'); - fterm_rawnum(arg2); - } - } - fterm_rawc(c); -} - -void -fterm_rawclear(void) -{ - fterm_rawhome(); - // ED: CSI n J, 0 = cursor to bottom, 2 = whole - fterm_raws(ESC_STR "[2J"); -} - -void -fterm_rawclreol(void) -{ -#ifdef FTCONF_CLEAR_SETATTR - // ftattr oattr = ft.rattr; - // XXX If we skip with "backround only" here, future updating - // may get wrong attributes. Or not? (consider DBCS...) - // if (FTATTR_GETBG(oattr) != FTATTR_GETBG(FTATTR_ERASE)) - fterm_rawattr(FTATTR_ERASE); -#endif - - // EL: CSI n K, n = 0 - fterm_raws(ESC_STR "[K"); - -#ifdef FTCONF_CLEAR_SETATTR - // No need to do so? because we will always reset attribute... - // fterm_rawattr(oattr); -#endif -} - -void -fterm_rawhome(void) -{ - // CUP: CSI n ; m H - fterm_raws(ESC_STR "[H"); - ft.rx = ft.ry = 0; -} - -void -fterm_rawmove_rel(int dy, int dx) -{ -#ifndef FTCONF_USE_ANSI_RELMOVE - // Old BBS system does not output relative moves (ESC[ABCD) . - // Poor terminals (ex, pcman-1.0.5-FF20.xpi) - // do not support relmoves - fterm_rawmove(ft.ry + dy, ft.rx + dx); -#else - if (!dx) - { - int y = ranged(dy + ft.ry, 0, ft.rows-1); - dy = y - ft.ry; - if (!dy) - return; - - fterm_rawcmd(abs(dy), 1, dy < 0 ? 'A' : 'B'); - ft.ry = y; - } - else if (!dy) - { - int x = ranged(dx + ft.rx, 0, ft.cols-1); - dx = x - ft.rx; - if (!dx) - return; - - fterm_rawcmd(abs(dx), 1, dx < 0 ? 'D' : 'C'); - ft.rx = x; - } - else - { - // (dy, dx) are given - use fterm_move. - fterm_rawmove(ft.ry + dy, ft.rx + dx); - } -#endif -} - -void -fterm_rawmove(int y, int x) -{ - y = ranged(y, 0, ft.rows-1); - x = ranged(x, 0, ft.cols-1); - - if (y == ft.ry && x == ft.rx) - return; - - // CUP: CSI n ; m H - fterm_rawcmd2(y+1, x+1, 1, 'H'); - - ft.ry = y; - ft.rx = x; -} - -void -fterm_rawmove_opt(int y, int x) -{ - // optimized move - int ady = abs(y-ft.ry), adx=abs(x-ft.rx); - - if (!adx && !ady) - return; - -#ifdef DBG_DISABLE_OPTMOVE - return fterm_rawmove(y, x); -#endif - - // known hacks: \r = (x=0), \b=(x--), \n = (y++) - // - // Warning: any optimization here should not change displayed content, - // because we don't have information about content variation information - // (eg, invalid DBCS bytes will become special marks) here. - // Any hacks which will try to display data from FTCMAP should be done - // inside dirty-map calculation, for ex, using spaces to move right, - // or re-print content. - -#ifndef DBG_TEXT_FD - // x=0: the cheapest output. However not work for text mode fd output. - // a special case is "if we have to move y to up". - // and FTCONF_ANSICMD2_OMIT < 1 (cannot omit x). -#if FTCONF_ANSICMD2_OMIT < 1 - if (y >= ft.ry) -#endif - if (adx && x == 0) - { - fterm_rawc('\r'); - ft.rx = x = adx = 0; - } - -#endif // !DBG_TEXT_FD - - // x--: compare with FTMV_COST: ESC[m;nH costs 5-8 bytes - if (x < ft.rx && y >= ft.ry && (adx+ady) < FTMV_COST) - { - while (adx > 0) - fterm_rawc('\b'), adx--; - ft.rx = x; - } - - // finishing movement - if (y > ft.ry && ady < FTMV_COST && adx == 0) - { - while (ft.ry++ < y) - fterm_rawc('\n'); - ft.ry = y; - } - else if (ady && adx) - { - fterm_rawmove(y, x); - } - else if (ady) - { - fterm_rawmove_rel(y-ft.ry, 0); - } - else if (adx) - { - fterm_rawmove_rel(0, x-ft.rx); - } -} - -void -fterm_rawcursor(void) -{ -#ifdef _WIN32 - COORD cursor; - cursor.X = ft.x; - cursor.Y = ft.y; - SetConsoleCursorPosition(hStdout, cursor); -#else - // fterm_rawattr(FTATTR_DEFAULT); - fterm_rawattr(ft.attr); - fterm_rawmove_opt(ft.y, ft.x); - fterm_rawflush(); -#endif // !_WIN32 -} - -void -fterm_rawscroll (int dy) -{ -#ifdef FTCONF_USE_ANSI_SCROLL - // SU: CSI n S (up) - // SD: CSI n T (down) - - char cmd = (dy > 0) ? 'S' : 'T'; - int ady = abs(dy); - if (ady == 0) - return; - if (ady >= ft.rows) ady = ft.rows; - fterm_rawcmd(ady, 1, cmd); - ft.scroll -= dy; - -#else - // VT100 flavor: - // * ESC D: scroll down - // * ESC M: scroll up - // - // Elder BBS systems works in a mixed way: - // \n at (rows-1) as scroll() - // and ESC-M at(0) as rscoll(). - // - // SCP: CSI s / RCP: CSI u - // Warning: cannot use SCP/RCP here, because on Win/DOS telnet - // the position will change after scrolling (ex, (25,0)->(24,0). - // - // Since scroll does not happen very often, let's relax and not - // optimize these commands here... - - int ady = abs(dy); - if (ady == 0) - return; - if (ady >= ft.rows) ady = ft.rows; - - // we are not going to preserve (rx,ry) - // so don't use fterm_move*. - if (dy > 0) - fterm_rawcmd2(ft.rows, 1, 1, 'H'); - else - fterm_rawcmd2(1, 1, 1, 'H'); - - for (; ady > 0; ady--) - { - if (dy >0) - { - // Win/DOS telnet may have extra text in new line, - // because of the IME line. -#ifdef FTCONF_USE_VT100_SCROLL - fterm_raws(ESC_STR "D" ESC_STR "[K"); // ESC_STR "[K"); -#else - fterm_raws("\n" ESC_STR "[K"); -#endif - } else { - fterm_raws(ESC_STR "M"); // ESC_STR "[K"); - } - } - - // Do not use optimized move here, because in poor terminals - // the coordinates are already out of sync. - fterm_rawcmd2(ft.ry+1, ft.rx+1, 1, 'H'); - ft.scroll -= dy; -#endif -} - -void -fterm_raws(const char *s) -{ - while (*s) - fterm_rawc(*s++); -} - -void -fterm_rawnc(int c, int n) -{ - while (n-- > 0) - fterm_rawc(c); -} - -////////////////////////////////////////////////////////////////////////// -// grayout advanced control -////////////////////////////////////////////////////////////////////////// -void -grayout(int y, int end, int level) -{ - char grattr = FTATTR_DEFAULT; - - y = ranged(y, 0, ft.rows-1); - end = ranged(end, 0, ft.rows-1); - - if (level == GRAYOUT_COLORBOLD) - { - int x = 0; - for (; y < end; y++) - { - for (x = 0; x < ft.cols-1; x++) - FTAMAP[y][x] |= FTATTR_BOLD; - } - return; - } - - if (level == GRAYOUT_COLORNORM) - { - int x = 0; - for (; y < end; y++) - { - for (x = 0; x < ft.cols-1; x++) - FTAMAP[y][x] &= ~(FTATTR_BLINK | FTATTR_BOLD); - } - return; - } - - if (level == GRAYOUT_BOLD) - { - grattr |= FTATTR_BOLD; - } - else if (level == GRAYOUT_DARK) - { - grattr = FTATTR_MAKE(0,0); - grattr |= FTATTR_BOLD; - } - else if (level == GRAYOUT_NORM) - { - // normal text - } - else - { - // not supported yet - } - - for (; y <= end; y++) - { - memset(FTAMAP[y], grattr, ft.cols); - } -} - -////////////////////////////////////////////////////////////////////////// -// deprecated api -////////////////////////////////////////////////////////////////////////// - -void -standout(void) -{ - outs(ANSI_COLOR(7)); -} - -void -standend(void) -{ - outs(ANSI_RESET); -} - -#ifndef _PFTERM_TEST_MAIN - -void -scr_dump(screen_backup_t *psb) -{ - int y = 0; - char *p = NULL; - - psb->row= ft.rows; - psb->col= ft.cols; - psb->y = ft.y; - psb->x = ft.x; - p = psb->raw_memory = - malloc (ft.rows * ft.cols * (sizeof(ftchar) + sizeof(ftattr))); - - for (y = 0; y < ft.rows; y++) - { - memcpy(p, FTCMAP[y], ft.cols * sizeof(ftchar)); - p += ft.cols * sizeof(ftchar); - memcpy(p, FTAMAP[y], ft.cols * sizeof(ftattr)); - p += ft.cols * sizeof(ftattr); - } -} - -void -scr_restore(const screen_backup_t *psb) -{ - int y = 0; - char *p = NULL; - int c = ft.cols, r = ft.rows; - if (!psb || !psb->raw_memory) - return; - - p = psb->raw_memory; - c = ranged(c, 0, psb->col); - r = ranged(r, 0, psb->row); - - ft.y = ranged(psb->y, 0, ft.rows-1); - ft.x = ranged(psb->x, 0, ft.cols-1); - clrscr(); - - for (y = 0; y < r; y++) - { - memcpy(FTCMAP[y], p, c * sizeof(ftchar)); - p += psb->col * sizeof(ftchar); - memcpy(FTAMAP[y], p, c * sizeof(ftattr)); - p += psb->col * sizeof(ftattr); - } - - free(psb->raw_memory); - ft.dirty = 1; - refresh(); -} - -void -move_ansi(int y, int x) -{ - move(y, x); -} - -void -getyx_ansi(int *y, int *x) -{ - getyx(y, x); -} - -void -region_scroll_up(int top, int bottom) -{ - int i; - ftchar *c0; - ftattr *a0; - - // logic same with old screen.c - if (top > bottom) { - i = top; - top = bottom; - bottom = i; - } - if (top < 0 || bottom >= ft.rows) - return; - - c0 = FTCMAP[top]; - a0 = FTAMAP[top]; - - for (i = top; i < bottom; i++) - { - FTCMAP[i] = FTCMAP[i+1]; - FTAMAP[i] = FTAMAP[i+1]; - } - FTCMAP[bottom] = c0; - FTAMAP[bottom] = a0; - - clrregion(bottom, bottom); - fterm_markdirty(); -} - -#endif - -////////////////////////////////////////////////////////////////////////// -// adapter -////////////////////////////////////////////////////////////////////////// - -int -fterm_inbuf(void) -{ -#ifdef _PFTERM_TEST_MAIN - return 0; -#else - return num_in_buf(); -#endif -} - -void -fterm_rawc(int c) -{ -#ifdef _PFTERM_TEST_MAIN - // if (c == ESC_CHR) putchar('*'); else - putchar(c); -#else - ochar(c); -#endif -} - -void -fterm_rawnewline(void) -{ -#ifdef _PFTERM_TEST_MAIN - putchar('\n'); -#else - ochar('\r'); - ochar('\n'); -#endif -} - -void -fterm_rawflush(void) -{ -#ifdef _PFTERM_TEST_MAIN - fflush(stdout); -#else - oflush(); -#endif -} - -////////////////////////////////////////////////////////////////////////// -// test -////////////////////////////////////////////////////////////////////////// - -#ifdef _PFTERM_TEST_MAIN -int main(int argc, char* argv[]) -{ - char buf[512]; - initscr(); - - if (argc < 2) - { -#if 0 - // DBCS test - char *a1 = ANSI_COLOR(1;33) "´ú¸Õ" ANSI_COLOR(34) "¤¤¤å" - ANSI_COLOR(7) "´ú¸Õ" ANSI_RESET "´ú¸Õ" - "´ú¸Õa" ANSI_RESET "\n"; - outstr(a1); - move(0, 2); - outstr("¤¤¤å1"); - outstr(ANSI_COLOR(1;33)"¤¤¤å2"); - outstr(" ¤¤\x85"); - outstr("okok herer\x8a"); - - move(0, 8); - inansistr(buf, sizeof(buf)-1); - - move(3,5); outs(ANSI_RESET "(From inansistr:) "); outs(buf); - move(7, 3); - sprintf(buf, "strlen()=%d\n", fterm_strdlen(a1)); - outstr(buf); - refresh(); - getchar(); - - outs(ANSI_COLOR(1;33) "test " ANSI_COLOR(34) "x" - ANSI_RESET "te" ANSI_COLOR(43;0;1;35) " st" - ANSI_COLOR(0) "testx\n"); - refresh(); - getchar(); - - clear(); - outs("¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å"); - move(0, 0); - outs(" this\xFF (ff)is te.(80 tail)->\x80 (80)"); - refresh(); - getchar(); -#endif - -#if 1 - // test resize - clear(); move(1, 0); outs("test resize\n"); - doupdate(); getchar(); - // expand X - resizeterm(25,200); - clear(); move(20, 0); clrtoeol(); outs("200x25"); - doupdate(); getchar(); - // resize back - resizeterm(25,80); - clear(); move(20, 0); clrtoeol(); outs("80x25"); - doupdate(); getchar(); - // expand Y - resizeterm(60,80); - clear(); move(20, 0); clrtoeol(); outs("80x60"); - doupdate(); getchar(); - // see if you crash here. - resizeterm(60,200); - clear(); move(20, 0); clrtoeol(); outs("200x60"); - doupdate(); getchar(); -#endif - -#if 0 - // test optimization - clear(); - move(1, 0); - outs("x++ optimization test\n"); - outs("1 2 3 4 5 6 7 8 9 0\n"); - outs("1122233334444455555566666667777777788888888899999999990\n"); - refresh(); - getchar(); - - move(2, 0); - outs("1122233334444455555566666667777777788888888899999999990\n"); - outs("1 2 3 4 5 6 7 8 9 0\n"); - refresh(); - getchar(); - - rscroll(); - refresh(); - getchar(); -#endif - } else { - FILE *fp = fopen(argv[1], "r"); - int c = 0; - - while (fp && (c=getc(fp)) > 0) - { - outc(c); - } - fclose(fp); - refresh(); - } - - endwin(); - printf("\ncomplete. enter to exit.\n"); - getchar(); - return 0; -} -#endif // _PFTERM_TEST_MAIN - -#endif // defined(EXP_PFTERM) || defined(USE_PFTERM) - -// vim:ts=4:sw=4:expandtab diff --git a/mbbsd/pmore.c b/mbbsd/pmore.c deleted file mode 100644 index fde26f3a..00000000 --- a/mbbsd/pmore.c +++ /dev/null @@ -1,3732 +0,0 @@ -/* $Id$ */ - -/* - * pmore: piaip's more, a new replacement for traditional pager - * - * piaip's new implementation of pager(more) with mmap, - * designed for unlimilited length(lines). - * - * "pmore" is "piaip's more", NOT "PTT's more"!!! - * pmore is designed for general maple-family BBS systems, not - * specific to any branch. - * - * Author: Hung-Te Lin (piaip), June 2005. - * - * Copyright(c) 2005-2008 Hung-Te Lin <piaip@csie.ntu.edu.tw> - * All Rights Reserved. - * You are free to use, modify, redistribute this program in any - * non-commercial usage (including network service). - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * MAJOR IMPROVEMENTS: - * - Clean source code, and more readable for mortal - * - Correct navigation - * - Excellent search ability (for correctness and user behavior) - * - Less memory consumption (mmap is not considered anyway) - * - Better support for large terminals - * - Unlimited file length and line numbers - * - * TODO AND DONE: - * - [2005, Initial Release] - * - Optimized speed up with Scroll supporting [done] - * - Wrap long lines [done] - * - Left-right wide navigation [done] - * - DBCS friendly wrap [done] - * - Reenrtance for main procedure [done] - * - Support PTT_PRINTS [done] - * - ASCII Art movie support [done] - * - ASCII Art movie navigation keys [pending] - * - A new optimized terminal base system (piterm) [dropped] - * - - * - [2007, Interactive Movie Enhancement] - * - New Invisible Frame Header Code [done] - * - Playback Control (pause, stop, skip) [done] - * - Interactive Movie (Hyper-text) [done] - * - Preference System (like board-conf) [done] - * - Traditional Movie Compatible Mode [done] - * - movie: Optimization on relative frame numbers [done] - * - movie: Optimization on named frames (by hash) - * - - * - Support Anti-anti-idle (ex, PCMan sends up-down) - * - Better help system [pending] - * - Virtual Contatenate [pending] - * - Drop ANSI between DBCS words if outputing UTF8 [drop, done by term] - */ - -// --------------------------------------------------------------- <FEATURES> -/* These are default values. - * You may override them in your bbs.h or config.h etc etc. - */ -#define PMORE_PRELOAD_SIZE (64*1024L) // on busy system set smaller or undef - -#define PMORE_USE_PTT_PRINTS // support PTT or special printing -#define PMORE_USE_OPT_SCROLL // optimized scroll -#define PMORE_USE_DBCS_WRAP // safe wrap for DBCS. -#define PMORE_USE_ASCII_MOVIE // support ascii movie -//#define PMORE_RESTRICT_ANSI_MOVEMENT // user cannot use ANSI escapes to move -#define PMORE_ACCURATE_WRAPEND // try more harder to find file end in wrap mode -#define PMORE_TRADITIONAL_PROMPTEND // when prompt=NA, show only page 1 -#define PMORE_TRADITIONAL_FULLCOL // to work with traditional ascii arts -#define PMORE_LOG_SYSOP_EDIT // log whenever sysop uses E -#define PMORE_OVERRIDE_TIME // override time format if possible - -// if you are working with a terminal without ANSI control, -// you are using a poor term (define PMORE_USING_POOR_TERM). -#ifndef USE_PFTERM // pfterm is a good terminal system. -#define PMORE_USING_POOR_TERM -#define PMORE_WORKAROUND_CLRTOEOL // try to work with poor terminal sys -#endif // USE_PFTERM -// -------------------------------------------------------------- </FEATURES> - -// ----------------------------------------------------------- <LOCALIZATION> -// Messages for localization are listed here. -#define PMORE_MSG_PREF_TITLE \ - " pmore 2007 ³]©w¿ï¶µ " -#define PMORE_MSG_PREF_TITLE_QRAW \ - " pmore 2007 §Ö³t³]©w¿ï¶µ - ¦â±m(ANSI½X)Åã¥Ü¼Ò¦¡ " -#define PMORE_MSG_WARN_FAKEUSERINFO \ - " ¡¶¦¹¶¤º®e·|¨Ì¾\\ŪªÌ¤£¦P,ì¤å¥¼¥²¦³±zªº¸ê®Æ " -#define PMORE_MSG_WARN_MOVECMD \ - " ¡¶¦¹¶¤º®e§t²¾¦ì½X,¥i¯à·|Åã¥Ü°°³yªº¨t²Î°T®§ " -#define PMORE_MSG_SEARCH_KEYWORD \ - "[·j´M]ÃöÁä¦r:" - -#define PMORE_MSG_MOVIE_DETECTED \ - " ¡¹ ³o¥÷¤å¥ó¬O¥i¼½©ñªº¤å¦r°Êµe¡An¶}©l¼½©ñ¶Ü¡H [Y/n]" -#define PMORE_MSG_MOVIE_PLAYOLD_GETTIME \ - "³o¥i¯à¬O¶Ç²Î°ÊµeÀÉ, Ynª½±µ¼½©ñ½Ð¿é¤J³t«×(¬í): " -#define PMORE_MSG_MOVIE_PLAYOLD_AS24L \ - "¶Ç²Î°Êµe¬O¥H 24 ¦æ¬°³æ¦ì³]pªº, n¼ÒÀÀ 24 ¦æ¶Ü? (§_«h·|¥Î²{¦bªº¦æ¼Æ)[Yn] " -#define PMORE_MSG_MOVIE_PAUSE \ - " >>> ¼È°±¼½©ñ°Êµe¡A½Ð«ö¥ô·NÁäÄ~Äò©Î q ¤¤Â_¡C <<<" -#define PMORE_MSG_MOVIE_PLAYING \ - " >>> °Êµe¼½©ñ¤¤... ¥i«ö q, Ctrl-C ©Î¨ä¥¦¥ô·NÁä°±¤î"; -#define PMORE_MSG_MOVIE_INTERACTION_PLAYING \ - " >>> ¤¬°Ê¦¡°Êµe¼½©ñ¤¤... ¥i«ö q ©Î Ctrl-C °±¤î"; -#define PMORE_MSG_MOVIE_INTERACTION_STOPPED \ - "¤w±j¨î¤¤Â_¤¬°Ê¦¡¨t²Î" - -// ----------------------------------------------------------- <LOCALIZATION> - -#include "bbs.h" - -#include <unistd.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <ctype.h> -#include <string.h> - -// Platform Related. NoSync is faster but if we don't have it... -// Experimental: POPULATE should work faster? -#ifdef MAP_NOSYNC -#define MF_MMAP_OPTION (MAP_NOSYNC|MAP_SHARED) -#elif defined(MAP_POPULATE) -#define MF_MMAP_OPTION (MAP_POPULATE|MAP_SHARED) -#else -#define MF_MMAP_OPTION (MAP_SHARED) -#endif - -/* Developer's Guide - * - * OVERVIEW - * - pmore is designed as a line-oriented pager. After you load (mf_attach) - * a file, you can move current display window by lines (mf_forward and - * mf_backward) and then display a page(mf_display). - * And please remember to delete allocated resources (mf_detach) - * when you exit. - * - Functions are designed to work with global variables. - * However you can overcome re-entrance problem by backuping up variables - * or replace all "." to "->" with little modification and add pointer as - * argument passed to each function. - * (This is really tested and it works, however then using global variables - * is considered to be faster and easier to maintain, at lease shorter in - * time to key-in and for filelength). - * - Basically this file should only export one function, "pmore". - * Using any other functions here may be dangerous because they are not - * coded for external reentrance rightnow. - * - mf_* are operation functions to work with file buffer. - * Usually these function assumes "mf" can be accessed. - * - pmore_* are utility functions - * - * DETAIL - * - The most tricky part of pmore is the design of "maxdisps" and "maxlinenoS". - * What do they mean? "The pointer and its line number of last page". - * - Because pmore is designed to work with very large files, it's costly to - * calculate the total line numbers (and not necessary). But if we don't - * know about how many lines left can we display then when navigating by - * pages may result in a page with single line conent (if you set display - * starting pointer to the real last line). - * - To overcome this issue, maxdisps is introduced. It tries to go backward - * one page from end of file (this operation is lighter than visiting - * entire file content for line number calculation). Then we can set this - * as boundary of forward navigation. - * - maxlinenoS is the line number of maxdisps. It's NOT the real number of - * total line in current file (You have to add the last page). That's why - * it has a strange name of trailing "S", to hint you that it's not - * "maxlineno" which is easily considered as "max(total) line number". - * - * HINTS: - * - Remember mmap pointers are NOT null terminated strings. - * You have to use strn* APIs and make sure not exceeding mmap buffer. - * DO NOT USE strcmp, strstr, strchr, ... - * - Scroll handling is painful. If you displayed anything on screen, - * remember to MFDISP_DIRTY(); - * - To be portable between most BBS systems, pmore is designed to - * workaround most BBS bugs inside itself. - * - Basically pmore considered the 'outc' output system as unlimited buffer. - * However on most BBS implementation, outc used a buffer with ANSILINELEN - * in length. And for some branches they even used unsigned byte for index. - * So if user complained about output truncated or blanked, increase buffer. - */ - -#ifdef DEBUG -int debug = 0; -# define MFPROTO -#else -# define MFPROTO inline static -#endif - -/* DBCS users tend to write unsigned char. let's make compiler happy */ -#define ustrlen(x) strlen((char*)x) -#define ustrchr(x,y) (unsigned char*)strchr((char*)x, y) -#define ustrrchr(x,y) (unsigned char*)strrchr((char*)x, y) - - -// --------------------------------------------- <Defines and constants> - -// --------------------------- <Display> - -/* ANSI COMMAND SYSTEM */ -/* On some systems with pmore style ANSI system applied, - * we don't have to define these again. - */ -#ifndef PMORE_STYLE_ANSI -#define PMORE_STYLE_ANSI - -// Escapes. I don't like \033 everywhere. -#define ESC_NUM (0x1b) -#define ESC_STR "\x1b" -#define ESC_CHR '\x1b' - -// Common ANSI commands. -#define ANSI_RESET ESC_STR "[m" -#define ANSI_COLOR(x) ESC_STR "[" #x "m" -#define ANSI_CLRTOEND ESC_STR "[K" -#define ANSI_MOVETO(y,x) ESC_STR "[" #y ";" #x "H" - -#define ANSI_IN_ESCAPE(x) (((x) >= '0' && (x) <= '9') || \ - (x) == ';' || (x) == ',' || (x) == '[') - -#endif /* PMORE_STYLE_ANSI */ - -#define ANSI_IN_MOVECMD(x) (strchr("ABCDfjHJRu", x) != NULL) -#define PMORE_DBCS_LEADING(c) (c >= 0x80) - -// Poor BBS terminal system Workarounds -// - Most BBS implements clrtoeol() as fake command -// and usually messed up when output ANSI quoted string. -// - A workaround is suggested by kcwu: -// https://opensvn.csie.org/traccgi/pttbbs/trac.cgi/changeset/519 -#define FORCE_CLRTOEOL() outs(ANSI_CLRTOEND) - -/* Again, if you have a BBS system which optimized out* without recognizing - * ANSI escapes, scrolling with ANSI text may result in melformed text (because - * ANSI escapes were "optimized" ). So here we provide a method to overcome - * with this situation. However your should increase your I/O buffer to prevent - * flickers. - */ -MFPROTO void -pmore_clrtoeol(int y, int x) -{ -#ifdef PMORE_WORKAROUND_CLRTOEOL - int i; - move(y, x); - for (i = x; i < t_columns; i++) - outc(' '); - clrtoeol(); - move(y, x); // this is required, due to outc(). -#else - move(y, x); - clrtoeol(); -#endif -} - -// --------------------------- </Display> - -// --------------------------- <Main Navigation> -typedef struct -{ - unsigned char - *start, *end, // file buffer - *disps, *dispe, // displayed content start/end - *maxdisps; // a very special pointer, - // consider as "disps of last page" - off_t len; // file total length - long lineno, // lineno of disps - oldlineno, // last drawn lineno, < 0 means full update - xpos, // starting x position - // - wraplines, // wrapped lines in last display - trunclines, // truncated lines in last display - dispedlines, // how many different lines displayed - // usually dispedlines = PAGE-wraplines, - // but if last line is incomplete(wrapped), - // dispedlines = PAGE-wraplines + 1 - lastpagelines,// lines of last page to show - // this indicates how many lines can - // maxdisps(maxlinenoS) display. - maxlinenoS; // lineno of maxdisps, "S"! - // What does the magic "S" mean? - // Just trying to notify you that it's - // NOT REAL MAX LINENO NOR FILELENGTH!!! - // You may consider "S" of "Start" (disps). -} MmappedFile; - -MmappedFile mf = { - 0, 0, 0, 0, 0, 0L, - 0, -1L, 0, 0, -1L, -1L, -1L,-1L -}; // current file - -/* mf_* navigation commands return value meanings */ -enum MF_NAV_COMMANDS { - MFNAV_OK, // navigation ok - MFNAV_EXCEED, // request exceeds buffer -}; - -/* Navigation units (dynamic, so not in enum const) */ -#define MFNAV_PAGE (t_lines-2) // when navigation, how many lines in a page to move - -/* Display system */ -enum MF_DISP_CONST { - /* newline method (because of poor BBS implementation) */ - MFDISP_NEWLINE_CLEAR = 0, // \n and cleartoeol - MFDISP_NEWLINE_SKIP, - MFDISP_NEWLINE_MOVE, // use move to simulate newline. - - MFDISP_OPT_CLEAR = 0, - MFDISP_OPT_OPTIMIZED, - MFDISP_OPT_FORCEDIRTY, - - // prefs - - MFDISP_WRAP_TRUNCATE = 0, - MFDISP_WRAP_WRAP, - MFDISP_WRAP_MODES, - - MFDISP_SEP_NONE = 0x00, - MFDISP_SEP_LINE = 0x01, - MFDISP_SEP_WRAP = 0x02, - MFDISP_SEP_OLD = MFDISP_SEP_LINE | MFDISP_SEP_WRAP, - MFDISP_SEP_MODES= 0x04, - - MFDISP_RAW_NA = 0x00, - MFDISP_RAW_NOANSI, - MFDISP_RAW_PLAIN, - MFDISP_RAW_MODES, - -}; - -#define MFDISP_PAGE (t_lines-1) // the real number of lines to be shown. -#define MFDISP_DIRTY() { mf.oldlineno = -1; } - -/* Indicators */ -#define MFDISP_TRUNC_INDICATOR ANSI_COLOR(0;1;37) ">" ANSI_RESET -#define MFDISP_WRAP_INDICATOR ANSI_COLOR(0;1;37) "\\" ANSI_RESET -#define MFDISP_WNAV_INDICATOR ANSI_COLOR(0;1;37) "<" ANSI_RESET -// --------------------------- </Main Navigation> - -// --------------------------- <Aux. Structures> -/* browsing preference */ -typedef struct -{ - /* mode flags */ - unsigned char - wrapmode, // wrap? - separator, // separator style - wrapindicator, // show wrap indicators - - oldwrapmode, // traditional wrap - oldstatusbar, // traditional statusbar - rawmode; // show file as-is. -} MF_BrowsingPreference; - -MF_BrowsingPreference bpref = -{ MFDISP_WRAP_WRAP, MFDISP_SEP_OLD, 1, - 0, 0, 0, }; - -/* pretty format header */ -#define FH_HEADERS (4) // how many headers do we know? -#define FH_HEADER_LEN (4) // strlen of each heads -#define FH_FLOATS (2) // right floating, name and val -static const char *_fh_disp_heads[FH_HEADERS] = - {"§@ªÌ", "¼ÐÃD", "®É¶¡", "Âà«H"}; - -typedef struct -{ - int lines; // header lines - unsigned char *headers[FH_HEADERS]; - unsigned char *floats [FH_FLOATS]; -} MF_PrettyFormattedHeader; - -MF_PrettyFormattedHeader fh = { 0, {0,0,0,0}, {0, 0}}; - -/* search records */ -typedef struct -{ - int len; - int (*cmpfunc) (const char *, const char *, size_t); - unsigned char *search_str; // maybe we can change to dynamic allocation -} MF_SearchRecord; - -MF_SearchRecord sr = { 0, strncmp, NULL}; - -enum MFSEARCH_DIRECTION { - MFSEARCH_FORWARD, - MFSEARCH_BACKWARD, -}; - -// Reset structures -#define RESETMF() { memset(&mf, 0, sizeof(mf)); \ - mf.lastpagelines = mf.maxlinenoS = mf.oldlineno = -1; } -#define RESETFH() { memset(&fh, 0, sizeof(fh)); \ - fh.lines = -1; } - -// Artwork -#define OPTATTR_NORMAL ANSI_COLOR(0;34;47) -#define OPTATTR_NORMAL_KEY ANSI_COLOR(0;31;47) -#define OPTATTR_SELECTED ANSI_COLOR(0;1;37;46) -#define OPTATTR_SELECTED_KEY ANSI_COLOR(0;31;46) -#define OPTATTR_BAR ANSI_COLOR(0;1;30;47) - -// --------------------------- </Aux. Structures> - -// --------------------------------------------- </Defines and constants> - -// --------------------------------------------- <Optional Modules> -#ifdef PMORE_USE_ASCII_MOVIE -enum _MFDISP_MOVIE_MODES { - MFDISP_MOVIE_UNKNOWN= 0, - MFDISP_MOVIE_DETECTED, - MFDISP_MOVIE_YES, - MFDISP_MOVIE_NO, - MFDISP_MOVIE_PLAYING, - MFDISP_MOVIE_PLAYING_OLD, -}; - -typedef struct { - struct timeval frameclk; - struct timeval synctime; - unsigned char *options, - *optkeys; - unsigned char mode, - compat24, - interactive, - pause; -} MF_Movie; - -MF_Movie mfmovie; - -#define STOP_MOVIE() { \ - mfmovie.options = NULL; \ - mfmovie.pause = 0; \ - if (mfmovie.mode == MFDISP_MOVIE_PLAYING) \ - mfmovie.mode = MFDISP_MOVIE_YES; \ - if (mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD) \ - mfmovie.mode = MFDISP_MOVIE_NO; \ - mf_determinemaxdisps(MFNAV_PAGE, 0); \ - mf_forward(0); \ -} - -#define RESET_MOVIE() { \ - mfmovie.mode = MFDISP_MOVIE_UNKNOWN; \ - mfmovie.options = NULL; \ - mfmovie.optkeys = NULL; \ - mfmovie.compat24 = 1; \ - mfmovie.pause = 0; \ - mfmovie.interactive = 0; \ - mfmovie.synctime.tv_sec = mfmovie.synctime.tv_usec = 0; \ - mfmovie.frameclk.tv_sec = 1; mfmovie.frameclk.tv_usec = 0; \ -} - -#define MOVIE_IS_PLAYING() \ - ((mfmovie.mode == MFDISP_MOVIE_PLAYING) || \ - (mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD)) - -unsigned char * - mf_movieFrameHeader(unsigned char *p, unsigned char *end); - -int pmore_wait_key(struct timeval *ptv, int dorefresh); -int mf_movieNextFrame(); -int mf_movieSyncFrame(); -int mf_moviePromptPlaying(int type); -int mf_movieMaskedInput(int c); - -void mf_float2tv(float f, struct timeval *ptv); - -#define MOVIE_MIN_FRAMECLK (0.1f) -#define MOVIE_MAX_FRAMECLK (3600.0f) -#define MOVIE_SECOND_U (1000000L) -#define MOVIE_ANTI_ANTI_IDLE - -// some magic value that your igetch() will never return -#define MOVIE_KEY_ANY (0x4d464b41) - -#ifndef MOVIE_KEY_BS2 -#define MOVIE_KEY_BS2 (0x7f) -#endif - -#endif -// --------------------------------------------- </Optional Modules> - -// used by mf_attach -void mf_parseHeaders(); -void mf_freeHeaders(); -void mf_determinemaxdisps(int, int); - -/* - * mmap basic operations - */ -int -mf_attach(const char *fn) -{ - struct stat st; - int fd = open(fn, O_RDONLY, 0600); - - if(fd < 0) - return 0; - - if (fstat(fd, &st) || ((mf.len = st.st_size) <= 0) || S_ISDIR(st.st_mode)) - { - mf.len = 0; - close(fd); - return 0; - } - - /* - mf.len = lseek(fd, 0L, SEEK_END); - lseek(fd, 0, SEEK_SET); - */ - - mf.start = mmap(NULL, mf.len, PROT_READ, - MF_MMAP_OPTION, fd, 0); - close(fd); - - if(mf.start == MAP_FAILED) - { - RESETMF(); - return 0; - } - - // BSD mmap advise. comment if your OS does not support this. - madvise(mf.start, mf.len, MADV_SEQUENTIAL); - - mf.end = mf.start + mf.len; - mf.disps = mf.dispe = mf.start; - mf.lineno = 0; - - mf_determinemaxdisps(MFNAV_PAGE, 0); - - mf.disps = mf.dispe = mf.start; - mf.lineno = 0; - - /* reset and parse article header */ - mf_parseHeaders(); - - /* a workaround for wrapped separators */ - if(mf.maxlinenoS > 0 && - fh.lines >= mf.maxlinenoS && - bpref.separator & MFDISP_SEP_WRAP) - { - mf_determinemaxdisps(+1, 1); - } - - return 1; -} - -void -mf_detach() -{ - mf_freeHeaders(); - if(mf.start) { - munmap(mf.start, mf.len); - RESETMF(); - } -} - -/* - * lineno calculation, and moving - */ -void -mf_sync_lineno() -{ - unsigned char *p; - - if(mf.disps == mf.maxdisps && mf.maxlinenoS >= 0) - { - mf.lineno = mf.maxlinenoS; - } else { - mf.lineno = 0; - for (p = mf.start; p < mf.disps; p++) - if(*p == '\n') - mf.lineno ++; - - if(mf.disps == mf.maxdisps && mf.maxlinenoS < 0) - mf.maxlinenoS = mf.lineno; - } -} - -MFPROTO int mf_backward(int); // used by mf_buildmaxdisps -MFPROTO int mf_forward(int); // used by mf_buildmaxdisps - -void -mf_determinemaxdisps(int backlines, int update_by_offset) -{ - unsigned char *pbak = mf.disps, *mbak = mf.maxdisps; - long lbak = mf.lineno; - - if(update_by_offset) - { - if(backlines > 0) - { - /* tricky way because usually - * mf_forward checks maxdisps. - */ - mf.disps = mf.maxdisps; - mf.maxdisps = mf.end-1; - mf_forward(backlines); - mf_backward(0); - } else - mf_backward(backlines); - } else { - mf.lineno = backlines; - mf.disps = mf.end - 1; - backlines = mf_backward(backlines); - } - - if(mf.disps != mbak) - { - mf.maxdisps = mf.disps; - if(update_by_offset) - mf.lastpagelines -= backlines; - else - mf.lastpagelines = backlines; - - mf.maxlinenoS = -1; -#ifdef PMORE_PRELOAD_SIZE - if(mf.len <= PMORE_PRELOAD_SIZE) - mf_sync_lineno(); // maxlinenoS will be automatically updated -#endif - } - mf.disps = pbak; - mf.lineno = lbak; -} - -/* - * mf_backwards is also used for maxno determination, - * so we cannot change anything in mf except these: - * mf.disps - * mf.lineno - */ -MFPROTO int -mf_backward(int lines) -{ - int real_moved = 0; - - /* backward n lines means to find n times of '\n'. */ - - /* if we're already in a line break, add one mark. */ - if (mf.disps < mf.end && *mf.disps == '\n') - lines++, real_moved --; - - while (1) - { - if (mf.disps < mf.start || *mf.disps == '\n') - { - real_moved ++; - if(lines-- <= 0 || mf.disps < mf.start) - break; - } - mf.disps --; - } - - /* now disps points to previous 1 byte of new address */ - mf.disps ++; - real_moved --; - mf.lineno -= real_moved; - - return real_moved; -} - -MFPROTO int -mf_forward(int lines) -{ - int real_moved = 0; - - while(mf.disps <= mf.maxdisps && lines > 0) - { - while (mf.disps <= mf.maxdisps && *mf.disps++ != '\n'); - - if(mf.disps <= mf.maxdisps) - mf.lineno++, lines--, real_moved++; - } - - if(mf.disps > mf.maxdisps) - mf.disps = mf.maxdisps; - - /* please make sure you have lineno synced. */ - if(mf.disps == mf.maxdisps && mf.maxlinenoS < 0) - mf.maxlinenoS = mf.lineno; - - return real_moved; - /* - if(lines > 0) - return MFNAV_OK; - else - return MFNAV_EXCEED; - */ -} - -int -mf_goTop() -{ - if(mf.disps == mf.start && mf.xpos > 0) - mf.xpos = 0; - mf.disps = mf.start; - mf.lineno = 0; - return MFNAV_OK; -} - -int -mf_goBottom() -{ - mf.disps = mf.maxdisps; - mf_sync_lineno(); - - return MFNAV_OK; -} - -MFPROTO int -mf_goto(int lineno) -{ - mf.disps = mf.start; - mf.lineno = 0; - return mf_forward(lineno); -} - -MFPROTO int -mf_viewedNone() -{ - return (mf.disps <= mf.start); -} - -MFPROTO int -mf_viewedAll() -{ - return (mf.dispe >= mf.end); -} -/* - * search! - */ -int -mf_search(int direction) -{ - unsigned char *s = sr.search_str; - int l = sr.len; - int flFound = 0; - - if(!s || !*s) - return 0; - - if(direction == MFSEARCH_FORWARD) - { - mf_forward(1); - while(mf.disps < mf.end - l) - { - if(sr.cmpfunc((char*)mf.disps, (char*)s, l) == 0) - { - flFound = 1; - break; - } else { - /* DBCS check here. */ - if(PMORE_DBCS_LEADING(*mf.disps++)) - mf.disps++; - } - } - mf_backward(0); - if(mf.disps > mf.maxdisps) - mf.disps = mf.maxdisps; - mf_sync_lineno(); - } - else if(direction == MFSEARCH_BACKWARD) - { - mf_backward(1); - while (!flFound && mf.disps > mf.start) - { - while(!flFound && mf.disps < mf.end-l && *mf.disps != '\n') - { - if(sr.cmpfunc((char*)mf.disps, (char*)s, l) == 0) - { - flFound = 1; - } else - { - /* DBCS check here. */ - if(PMORE_DBCS_LEADING(*mf.disps++)) - mf.disps++; - } - } - if(!flFound) - mf_backward(1); - } - mf_backward(0); - if(mf.disps < mf.start) - mf.disps = mf.start; - mf_sync_lineno(); - } - if(flFound) - MFDISP_DIRTY(); - return flFound; -} - -/* String Processing - * - * maybe you already have your string processors (or not). - * whether yes or no, here we provides some. - */ - -#define ISSPACE(x) (x <= ' ') - -MFPROTO void -pmore_str_strip_ansi(unsigned char *p) // warning: p is NULL terminated -{ - unsigned char *pb = p; - while (*p != 0) - { - if (*p == ESC_CHR) - { - // ansi code sequence, ignore them. - pb = p++; - while (ANSI_IN_ESCAPE(*p)) - p++; - memmove(pb, p, ustrlen(p)+1); - p = pb; - } - else if (*p < ' ' || *p == 0xff) - { - // control codes, ignore them. - // what is 0xff? old BBS does not handle telnet protocol - // so IACs were inserted. - memmove(p, p+1, ustrlen(p+1)+1); - } - else - p++; - } -} - -/* this chomp is a little different: - * it kills starting and trailing spaces. - */ -MFPROTO void -pmore_str_chomp(unsigned char *p) -{ - unsigned char *pb = p + ustrlen(p)-1; - - while (pb >= p) - if(ISSPACE(*pb)) - *pb-- = 0; - else - break; - pb = p; - while (*pb && ISSPACE(*pb)) - pb++; - - if(pb != p) - memmove(p, pb, ustrlen(pb)+1); -} - -#if 0 -int -pmore_str_safe_big5len(unsigned char *p) -{ - return 0; -} -#endif - -/* - * Format Related - */ - -void -mf_freeHeaders() -{ - if(fh.lines > 0) - { - int i; - - for (i = 0; i < FH_HEADERS; i++) - free(fh.headers[i]); - for (i = 0; i < FH_FLOATS; i++) - free(fh.floats[i]); - RESETFH(); - } -} - -void -mf_parseHeaders() -{ - /* file format: - * AUTHOR: author BOARD: blah <- headers[0], floats[0], floats[1] - * XXX: xxx <- headers[1] - * XXX: xxx <- headers[n] - * [blank, fill with separator] <- lines - * - * #define STR_AUTHOR1 "§@ªÌ:" - * #define STR_AUTHOR2 "µo«H¤H:" - */ - unsigned char *pmf = mf.start; - int i = 0; - - RESETFH(); - - if(mf.len < LEN_AUTHOR2) - return; - - if (strncmp((char*)mf.start, STR_AUTHOR1, LEN_AUTHOR1) == 0) - { - fh.lines = 3; // local - } - else if (strncmp((char*)mf.start, STR_AUTHOR2, LEN_AUTHOR2) == 0) - { - fh.lines = 4; - } - else - return; - - for (i = 0; i < fh.lines; i++) - { - unsigned char *p = pmf, *pb = pmf; - int l; - - /* first, go to line-end */ - while(pmf < mf.end && *pmf != '\n') - pmf++; - if(pmf >= mf.end) - break; - p = pmf; - pmf ++; // move to next line. - - // p is pointing at a new line. (\n) - l = (int)(p - pb); -#ifdef CRITICAL_MEMORY - // kcwu: dirty hack, avoid 64byte slot. use 128byte slot instead. - if (l<100) { - p = (unsigned char*) malloc (100+1); - } else { - p = (unsigned char*) malloc (l+1); - } -#else - p = (unsigned char*) malloc (l+1); -#endif - fh.headers[i] = p; - memcpy(p, pb, l); - p[l] = 0; - - // now, postprocess p. - pmore_str_strip_ansi(p); - -#ifdef PMORE_OVERRIDE_TIME - // (deprecated: too many formats for newsgroup) - // try to see if this is a valid time line - // use strptime to convert -#endif // PMORE_OVERRIDE_TIME - - // strip to quotes[+1 space] - if((pb = ustrchr((char*)p, ':')) != NULL) - { - if(*(pb+1) == ' ') pb++; - memmove(p, pb, ustrlen(pb)+1); - } - - // kill staring and trailing spaces - pmore_str_chomp(p); - - // special case, floats are in line[0]. - if(i == 0 && (pb = ustrrchr(p, ':')) != NULL && *(pb+1)) - { - unsigned char *np = (unsigned char*)strdup((char*)(pb+1)); - - fh.floats[1] = np; - pmore_str_chomp(np); - // remove quote and traverse back - *pb-- = 0; - while (pb > p && *pb != ',' && !(ISSPACE(*pb))) - pb--; - - if (pb > p) { - fh.floats[0] = (unsigned char*)strdup((char*)(pb+1)); - pmore_str_chomp(fh.floats[0]); - *pb = 0; - pmore_str_chomp(fh.headers[0]); - } else { - fh.floats[0] = (unsigned char*)strdup(""); - } - } - } -} - -/* - * mf_display utility macros - */ -MFPROTO void -MFDISP_SKIPCURLINE() -{ - while (mf.dispe < mf.end && *mf.dispe != '\n') - mf.dispe++; -} - -MFPROTO int -MFDISP_PREDICT_LINEWIDTH(unsigned char *p) -{ - /* predict from p to line-end, without ANSI seq. - */ - int off = 0; - int inAnsi = 0; - - while (p < mf.end && *p != '\n') - { - if(inAnsi) - { - if(!ANSI_IN_ESCAPE(*p)) - inAnsi = 0; - } else { - if(*p == ESC_CHR) - inAnsi = 1; - else - off ++; - } - p++; - } - return off; -} - -MFPROTO int -MFDISP_DBCS_HEADERWIDTH(int originalw) -{ - return originalw - (originalw %2); -// return (originalw >> 1) << 1; -} - -#define MFDISP_FORCEUPDATE2TOP() { startline = 0; } -#define MFDISP_FORCEUPDATE2BOT() { endline = MFDISP_PAGE - 1; } -#define MFDISP_FORCEDIRTY2BOT() \ - if(optimized == MFDISP_OPT_OPTIMIZED) { \ - optimized = MFDISP_OPT_FORCEDIRTY; \ - MFDISP_FORCEUPDATE2BOT(); \ - } - -static char *override_msg = NULL; -static char *override_attr = NULL; - -#define RESET_OVERRIDE_MSG() { override_attr = override_msg = NULL; } - -/* - * display mf content from disps for MFDISP_PAGE - */ - -void -mf_display() -{ - int lines = 0, col = 0, currline = 0, wrapping = 0; - int startline, endline; - int needMove2bot = 0; - - int optimized = MFDISP_OPT_CLEAR; - - /* why t_columns-1 here? - * because BBS systems usually have a poor terminal system - * and many stupid clients behave differently. - * So we try to avoid using the last column, leave it for - * BBS to place '\n' and CLRTOEOL. - */ - const int headerw = MFDISP_DBCS_HEADERWIDTH(t_columns-1); - const int dispw = headerw - (t_columns - headerw < 2); - const int maxcol = dispw - 1; - int newline_default = MFDISP_NEWLINE_CLEAR; - - if(mf.wraplines || mf.trunclines) - MFDISP_DIRTY(); // we can't scroll with wrapped lines. - - mf.wraplines = 0; - mf.trunclines = 0; - mf.dispedlines = 0; - - MFDISP_FORCEUPDATE2TOP(); - MFDISP_FORCEUPDATE2BOT(); - -#ifdef PMORE_USE_OPT_SCROLL - -#if defined(PMORE_USE_ASCII_MOVIE) && !defined(PMORE_USING_POOR_TERM) - // For movies, maybe clear() is better. - // Let's enable for good terminals (which does not need workarounds) - if (MOVIE_IS_PLAYING()) - { - clear(); move(0, 0); - } else -#endif // PMORE_USE_ASCII_MOVIE && (!PMORE_USING_POOR_TERM) - - /* process scrolling */ - if (mf.oldlineno >= 0 && mf.oldlineno != mf.lineno) - { - int scrll = mf.lineno - mf.oldlineno, i; - int reverse = (scrll > 0 ? 0 : 1); - - if(reverse) - scrll = -scrll; - else - { - /* because bottom status line is also scrolled, - * we have to erase it here. - */ - pmore_clrtoeol(b_lines, 0); - // move(b_lines, 0); - // clrtoeol(); - } - - if(scrll > MFDISP_PAGE) - scrll = MFDISP_PAGE; - - i = scrll; - -#if defined(USE_PFTERM) - // In fact, pfterm will flash black screen when scrolling pages... - // So it may work better if we refresh whole screen. - if (i >= b_lines / 2) - { - clear(); move(0, 0); - scrll = MFDISP_PAGE; - } else -#endif // defined(USE_PFTERM) - - while(i-- > 0) - if (reverse) - rscroll(); // v - else - scroll(); // ^ - - if(reverse) - { - endline = scrll-1; // v - // clear the line which will be scrolled - // to bottom (status line position). - pmore_clrtoeol(b_lines, 0); - // move(b_lines, 0); - // clrtoeol(); - } - else - { - startline = MFDISP_PAGE - scrll; // ^ - } - move(startline, 0); - optimized = MFDISP_OPT_OPTIMIZED; - // return; // uncomment if you want to observe scrolling - } - else -#endif - clear(), move(0, 0); - - mf.dispe = mf.disps; - while (lines < MFDISP_PAGE) - { - int inAnsi = 0; - int newline = newline_default; - int predicted_linewidth = -1; - int xprefix = mf.xpos; - -#ifdef PMORE_USE_DBCS_WRAP - unsigned char *dbcs_incomplete = NULL; -#endif - - currline = mf.lineno + lines; - col = 0; - - if(!wrapping && mf.dispe < mf.end) - mf.dispedlines++; - - if(optimized == MFDISP_OPT_FORCEDIRTY) - { - /* btw, apparently this line should be visible. - * if not, maybe something wrong. - */ - pmore_clrtoeol(lines, 0); - } - -#ifdef PMORE_USE_ASCII_MOVIE - if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD && - mfmovie.compat24) - { - if(mf.dispedlines == 23) - return; - } - else if (mfmovie.mode == MFDISP_MOVIE_DETECTED) - { - // detected only applies for first page. - // since this is not very often, let's prevent - // showing control codes. - if(mf_movieFrameHeader(mf.dispe, mf.end)) - MFDISP_SKIPCURLINE(); - } - else if(mfmovie.mode == MFDISP_MOVIE_UNKNOWN || - mfmovie.mode == MFDISP_MOVIE_PLAYING) - { - if(mf_movieFrameHeader(mf.dispe, mf.end)) - switch(mfmovie.mode) - { - - case MFDISP_MOVIE_UNKNOWN: - mfmovie.mode = MFDISP_MOVIE_DETECTED; - /* let's remove the first control sequence. */ - MFDISP_SKIPCURLINE(); - break; - - case MFDISP_MOVIE_PLAYING: - /* - * maybe we should do clrtobot() here, - * but it's even better if we do clear() - * all time. so we set dirty here for - * next frame, and please set dirty before - * playing. - */ - MFDISP_DIRTY(); - return; - } - } -#endif - - /* Is currentline visible? */ - if (lines < startline || lines > endline) - { - MFDISP_SKIPCURLINE(); - newline = MFDISP_NEWLINE_SKIP; - } - /* Now, consider what kind of line - * (header, separator, or normal text) - * is current line. - */ - else if (currline == fh.lines && bpref.rawmode == MFDISP_RAW_NA) - { - /* case 1, header separator line */ - if (bpref.separator & MFDISP_SEP_LINE) - { - outs(ANSI_COLOR(36)); - for(col = 0; col < headerw; col+=2) - { - // prints("%02d", col); - outs("¢w"); - } - outs(ANSI_RESET); - } - - /* Traditional 'more' adds separator as a newline. - * This is buggy, however we can support this - * by using wrapping features. - * Anyway I(piaip) don't like this. And using wrap - * leads to slow display (we cannt speed it up with - * optimized scrolling. - */ - if(bpref.separator & MFDISP_SEP_WRAP) - { - /* we have to do all wrapping stuff - * in normal text section. - * make sure this is updated. - */ - wrapping = 1; - mf.wraplines ++; - MFDISP_FORCEDIRTY2BOT(); - if(mf.dispe > mf.start && - mf.dispe < mf.end && - *mf.dispe == '\n') - mf.dispe --; - } - else - MFDISP_SKIPCURLINE(); - } - else if (currline < fh.lines && bpref.rawmode == MFDISP_RAW_NA ) - { - /* case 2, we're printing headers */ - const char *val = (const char*)fh.headers[currline]; - const char *name = _fh_disp_heads[currline]; - int w = headerw - FH_HEADER_LEN - 3; - - outs(ANSI_COLOR(47;34) " "); - outs(name); - outs(" " ANSI_COLOR(44;37) " "); - - /* right floating stuff? */ - if (currline == 0 && fh.floats[0]) - { - w -= ustrlen(fh.floats[0]) + ustrlen(fh.floats[1]) + 4; - } - - prints("%-*.*s", w, w, - (val ? val : "")); - - if (currline == 0 && fh.floats[0]) - { - outs(ANSI_COLOR(47;34) " "); - outs((const char*)fh.floats[0]); - outs(" " ANSI_COLOR(44;37) " "); - outs((const char*)fh.floats[1]); - outs(" "); - } - - outs(ANSI_RESET); - MFDISP_SKIPCURLINE(); - } - else if(mf.dispe < mf.end) - { - /* case 3, normal text */ - long dist = mf.end - mf.dispe; - long flResetColor = 0; - int srlen = -1; - int breaknow = 0; - - unsigned char c; - - if(xprefix > 0 && !bpref.oldwrapmode && bpref.wrapindicator) - { - outs(MFDISP_WNAV_INDICATOR); - col++; - } - - // first check quote - if(bpref.rawmode == MFDISP_RAW_NA) - { - if(dist > 1 && - (*mf.dispe == ':' || *mf.dispe == '>') && - *(mf.dispe+1) == ' ') - { - outs(ANSI_COLOR(36)); - flResetColor = 1; - } else if (dist > 2 && - (!strncmp((char*)mf.dispe, "¡°", 2) || - !strncmp((char*)mf.dispe, "==>", 3))) - { - outs(ANSI_COLOR(32)); - flResetColor = 1; - } - } - - while(!breaknow && mf.dispe < mf.end && (c = *mf.dispe) != '\n') - { - if(inAnsi) - { - if (!ANSI_IN_ESCAPE(c)) - inAnsi = 0; - /* whatever this is, output! */ - mf.dispe ++; - switch(bpref.rawmode) - { - case MFDISP_RAW_NOANSI: - /* TODO - * col++ here may be buggy. */ - if(col < t_columns) - { - /* we tried our best to determine */ - if(xprefix > 0) - xprefix --; - else - { - outc(c); - col++; - } - } - if(!inAnsi) - outs(ANSI_RESET); - break; - case MFDISP_RAW_PLAIN: - break; - - default: - if(ANSI_IN_MOVECMD(c)) - { -#ifdef PMORE_RESTRICT_ANSI_MOVEMENT - c = 's'; // "save cursor pos" -#else // PMORE_RESTRICT_ANSI_MOVEMENT - // some user cannot live without this. - // make them happy. - newline_default = newline = MFDISP_NEWLINE_MOVE; -#ifdef PMORE_USE_ASCII_MOVIE - // relax for movies - if (!MOVIE_IS_PLAYING()) -#endif // PMORE_USE_ASCII_MOVIE - { - override_attr = ANSI_COLOR(1;37;41); - override_msg = PMORE_MSG_WARN_MOVECMD; - } -#endif // PMORE_RESTRICT_ANSI_MOVEMENT - needMove2bot = 1; - } - outc(c); - break; - } - continue; - - } else { - - if(c == ESC_CHR) - { - inAnsi = 1; - /* we can't output now because maybe - * ptt_prints wants to do something. - */ - } - else if(sr.search_str && srlen < 0 && // support search -#ifdef PMORE_USE_DBCS_WRAP - dbcs_incomplete == NULL && -#endif - mf.end - mf.dispe > sr.len && - sr.cmpfunc((char*)mf.dispe, (char*)sr.search_str, sr.len) == 0) - { - outs(ANSI_COLOR(7)); - srlen = sr.len-1; - flResetColor = 1; - } - -#ifdef PMORE_USE_PTT_PRINTS - /* special case to resolve dirty Ptt_prints */ - if(inAnsi && - mf.end - mf.dispe > 2 && - *(mf.dispe+1) == '*') - { - int i; - char buf[64]; // make sure ptt_prints will not exceed - - memset(buf, 0, sizeof(buf)); - memcpy(buf, mf.dispe, 3); // ^[*s - mf.dispe += 2; - - if(bpref.rawmode) - buf[0] = '*'; - else - { -#ifdef LOW_SECURITY -# define PTTPRINT_WARN_PATTERN "slpnbm" -#else -# define PTTPRINT_WARN_PATTERN "slpn" -#endif // LOW_SECURITY - if(strchr(PTTPRINT_WARN_PATTERN, buf[2]) != NULL) - { - override_attr = ANSI_COLOR(1;37;41); - override_msg = PMORE_MSG_WARN_FAKEUSERINFO; - } - Ptt_prints(buf, sizeof(buf), NO_RELOAD); // result in buf - } - i = strlen(buf); - - if (col + i > maxcol) - i = maxcol - col; - if(i > 0) - { - buf[i] = 0; - col += i; - outs(buf); - } - inAnsi = 0; - } else -#endif - if(inAnsi) - { - switch(bpref.rawmode) - { - case MFDISP_RAW_NOANSI: - /* TODO - * col++ here may be buggy. */ - if(col < t_columns) - { - /* we tried our best to determine */ - if(xprefix > 0) - xprefix --; - else - { - outs(ANSI_COLOR(1) "*"); - col++; - } - } - break; - case MFDISP_RAW_PLAIN: - break; - default: - outc(ESC_CHR); - break; - } - } else { - int canOutput = 0; - /* if col > maxcol, - * because we have the space for - * "indicators" (one byte), - * so we can tolerate one more byte. - */ - if(col <= maxcol) // normal case - canOutput = 1; - else if (bpref.oldwrapmode && // oldwrapmode - col < t_columns) - { - canOutput = 1; - newline = MFDISP_NEWLINE_MOVE; - } else { - int off = 0; - // put more efforts to determine - // if we can use indicator space - // determine real offset between \n - if(predicted_linewidth < 0) - predicted_linewidth = col + 1 + - MFDISP_PREDICT_LINEWIDTH(mf.dispe+1); - off = predicted_linewidth - (col + 1); - - if (col + off <= (maxcol+1)) - { - canOutput = 1; // indicator space - } -#ifdef PMORE_TRADITIONAL_FULLCOL - else if (col + off < t_columns) - { - canOutput = 1; - newline = MFDISP_NEWLINE_MOVE; - } -#endif - } - - if(canOutput) - { - /* the real place to output text - */ -#ifdef PMORE_USE_DBCS_WRAP - if(mf.xpos > 0 && dbcs_incomplete && col < 2) - { - /* col = 0 or 1 only */ - if(col == 0) /* no indicators */ - c = ' '; - else if(!bpref.oldwrapmode && bpref.wrapindicator) - c = ' '; - } - - if (dbcs_incomplete) - dbcs_incomplete = NULL; - else if(PMORE_DBCS_LEADING(c)) - dbcs_incomplete = mf.dispe; -#endif - if(xprefix > 0) - xprefix --; - else - { - outc(c); - col++; - } - - if (srlen == 0) - outs(ANSI_RESET); - if(srlen >= 0) - srlen --; - } - else - /* wrap modes */ - if(mf.xpos > 0 || bpref.wrapmode == MFDISP_WRAP_TRUNCATE) - { - breaknow = 1; - mf.trunclines ++; - MFDISP_SKIPCURLINE(); - wrapping = 0; - } - else if (bpref.wrapmode == MFDISP_WRAP_WRAP) - { - breaknow = 1; - wrapping = 1; - mf.wraplines ++; -#ifdef PMORE_USE_DBCS_WRAP - if(dbcs_incomplete) - { - mf.dispe = dbcs_incomplete; - dbcs_incomplete = NULL; - /* to be more dbcs safe, - * use the followings to - * erase printed character. - */ - if(col > 0) { - /* TODO BUG BUGGY - * using move is maybe actually non-sense - * because BBS terminal system cannot - * display this when ANSI escapes were used - * in same line. However, on most - * situation this works. - * So we used an alternative, forced ANSI - * move command. - */ - // move(lines, col-1); - char ansicmd[16]; - sprintf(ansicmd, ANSI_MOVETO(%d,%d), - lines+1, col-1+1); - /* to preven ANSI ESCAPE being tranlated as - * DBCS trailing byte. */ - outc(' '); - /* move back one column */ - outs(ansicmd); - /* erase it (previous leading byte)*/ - outc(' '); - /* go to correct position */ - outs(ansicmd); - } - } -#endif - } - } - } - if(!breaknow) - mf.dispe ++; - } - if(flResetColor) - outs(ANSI_RESET); - - /* "wrapping" should be only in normal text section. - * We don't support wrap within scrolling, - * so if we have to wrap, invalidate all lines. - */ - if(breaknow) - { - if(wrapping) - MFDISP_FORCEDIRTY2BOT(); - - if(!bpref.oldwrapmode && bpref.wrapindicator && col < t_columns) - { - if(wrapping) - outs(MFDISP_WRAP_INDICATOR); - else - outs(MFDISP_TRUNC_INDICATOR); - } else { - outs(ANSI_RESET); - } - } - else - wrapping = 0; - } - - if(mf.dispe < mf.end && *mf.dispe == '\n') - mf.dispe ++; - // else, we're in wrap mode. - - switch(newline) - { - case MFDISP_NEWLINE_SKIP: - break; - case MFDISP_NEWLINE_CLEAR: - FORCE_CLRTOEOL(); - outc('\n'); - break; - case MFDISP_NEWLINE_MOVE: - move(lines+1, 0); - break; - } - lines ++; - } - /* - * we've displayed the file. - * but if we got wrapped lines in last page, - * mf.maxdisps may be required to be larger. - */ - if(mf.disps == mf.maxdisps && mf.dispe < mf.end) - { - /* - * never mind if that's caused by separator - * however this code is rarely used now. - * only if no preload file. - */ - if (bpref.separator & MFDISP_SEP_WRAP && - mf.wraplines == 1 && - mf.lineno < fh.lines) - { - /* - * o.k, now we know maxline should be one line forward. - */ - mf_determinemaxdisps(+1, 1); - } else - { - /* not caused by separator? - * ok, then it's by wrapped lines. - * - * old flavor: go bottom: - * mf_determinemaxdisps(0) - * however we have "update" method now, - * so we can achieve more user friendly behavior. - */ - mf_determinemaxdisps(+mf.wraplines, 1); - } - } - mf.oldlineno = mf.lineno; - - if (needMove2bot) - move(b_lines, 0); -} - -/* --------------------- MAIN PROCEDURE ------------------------- */ -void pmore_Preference(); -void pmore_QuickRawModePref(); -void pmore_Help(); - -static const char * const pmore_help[] = { - "\0¾\\Ū¤å³¹¥\\¯àÁä¨Ï¥Î»¡©ú", - "\01´å¼Ð²¾°Ê¥\\¯àÁä", - "(k/¡ô) (j/¡õ/Enter) ¤W±²/¤U±²¤@¦æ", - "(^B/PgUp/BackSpace) ¤W±²¤@¶", - "(^F/PgDn/Space/¡÷) ¤U±²¤@¶", - "(,/</S-TAB)(./>/TAB) ¥ª/¥k±²°Ê", - "(0/g/Home) ($/G/End) Àɮ׶}ÀY/µ²§À", - "¼Æ¦rÁä 1-9 (;/:) ¸õ¦Ü¿é¤Jªº¶¼Æ©Î¦æ¼Æ", - "\01¶i¶¥¥\\¯àÁä", - "(/) (s) ·j´MÃöÁä¦r/¤Á´«¦Ü¨ä¥¦¬ÝªO", - "(n/N) «½Æ¥¿/¤Ï¦V·j´M", - "(f/b) ¸õ¦Ü¤U/¤W½g", - "(a/A) ¸õ¦Ü¦P¤@§@ªÌ¤U/¤W½g", - "(t/[-/]+) ¥DÃD¦¡¾\\Ū:´`§Ç/«e/«á½g", - "\01¨ä¥L¥\\¯àÁä", - - // the line below is already aligned, because of the backslash. - "(o)/(\\) ¿ï¶µ³]©w/¦â±mÅã¥Ü¼Ò¦¡", - -#if defined (PMORE_USE_ASCII_MOVIE) || defined(RET_DOCHESSREPLAY) - "(p)/(z) ¼½©ñ°Êµe/´Ñ§½¥´ÃÐ", -#endif // defined(PMORE_USE_ASCII_MOVIE) || defined(RET_DOCHESSREPLAY) -#ifdef RET_COPY2TMP - "(Ctrl-T) ¦s¤J¼È¦sÀÉ", -#endif - "(q/¡ö) (h/H/?/F1) µ²§ô/¥»»¡©úµe±", -#ifdef DEBUG - "(d) ¤Á´«°£¿ù(debug)¼Ò¦¡", -#endif - /* You don't have to delete this copyright line. - * It will be located in bottom of screen and overrided by - * status line. Only user with big terminals will see this :) - */ - "\01¥»¨t²Î¨Ï¥Î piaip ªº·s¦¡ÂsÄýµ{¦¡: pmore 2007, piaip's more", - NULL -}; -/* - * pmore utility macros - */ -MFPROTO void -PMORE_UINAV_FORWARDPAGE() -{ - /* Usually, a forward is just mf_forward(MFNAV_PAGE); - * but because of wrapped lines... - * This function is used when user tries to nagivate - * with page request. - * If you want to a real page forward, don't use this. - * That's why we have this special function. - */ - int i = mf.dispedlines - 1; - - if(mf_viewedAll()) - return; - - if(i < 1) - i = 1; - mf_forward(i); -} - -MFPROTO void -PMORE_UINAV_FORWARDLINE() -{ - if(mf_viewedAll()) - return; - mf_forward(1); -} - -#define REENTRANT_RESTORE() { mf = bkmf; fh = bkfh; } - -/* - * piaip's more, a replacement for old more - */ -int -pmore(char *fpath, int promptend) -{ - int flExit = 0, retval = 0; - int ch = 0; - int invalidate = 1; - - /* simple re-entrant hack - * I don't want to write pointers everywhere, - * and pmore should be simple enough (inside itself) - * so we can do so. - */ - - MmappedFile bkmf; - MF_PrettyFormattedHeader bkfh; - -#ifdef PMORE_USE_ASCII_MOVIE - RESET_MOVIE(); -#endif - - bkmf = mf; /* simple re-entrant hack */ - bkfh = fh; - RESETFH(); - RESETMF(); - - override_msg = NULL; /* elimiate pending errors */ - - STATINC(STAT_MORE); - if(!mf_attach(fpath)) - { - REENTRANT_RESTORE(); - return -1; - } - - clear(); - while(!flExit) - { - if(invalidate) - { - mf_display(); - invalidate = 0; - } - - /* in current implementation, - * we want to invalidate for each keypress. - */ - invalidate = 1; - -#ifdef PMORE_TRADITIONAL_PROMPTEND - - if(promptend == NA) - { -#ifdef PMORE_USE_ASCII_MOVIE - if(mfmovie.mode == MFDISP_MOVIE_DETECTED) - { - /* quick auto play */ - mfmovie.mode = MFDISP_MOVIE_YES; - RESET_MOVIE(); - mfmovie.mode = MFDISP_MOVIE_PLAYING; - mf_determinemaxdisps(0, 0); // display until last line - mf_movieNextFrame(); - MFDISP_DIRTY(); - continue; - } else if (mfmovie.mode != MFDISP_MOVIE_PLAYING) -#endif - break; - } -#else - if(promptend == NA && mf_viewedAll()) - break; -#endif - move(b_lines, 0); - // clrtoeol(); // this shall be done in mf_display to speed up. - -#ifdef USE_BBSLUA - // TODO prompt BBS Lua status here. -#endif // USE_BBSLUA - -#ifdef PMORE_USE_ASCII_MOVIE - switch (mfmovie.mode) - { - case MFDISP_MOVIE_UNKNOWN: - mfmovie.mode = MFDISP_MOVIE_NO; - break; - - case MFDISP_MOVIE_DETECTED: - mfmovie.mode = MFDISP_MOVIE_YES; - { - // query if user wants to play movie. - - int w = t_columns-1; - const char *s = PMORE_MSG_MOVIE_DETECTED; - - outs(ANSI_RESET ANSI_COLOR(1;33;44)); - w -= strlen(s); outs(s); - - while(w-- > 0) outc(' '); outs(ANSI_RESET ANSI_CLRTOEND); - w = tolower(igetch()); - - if( w != 'n' && - w != KEY_UP && w != KEY_LEFT && - w != 'q') - { - RESET_MOVIE(); - mfmovie.mode = MFDISP_MOVIE_PLAYING; - mf_determinemaxdisps(0, 0); // display until last line - mf_movieNextFrame(); - MFDISP_DIRTY(); - // remove override messages - RESET_OVERRIDE_MSG(); - continue; - } - /* else, we have to clean up. */ - move(b_lines, 0); - clrtoeol(); - } - break; - - case MFDISP_MOVIE_PLAYING_OLD: - case MFDISP_MOVIE_PLAYING: - - mf_moviePromptPlaying(0); - - // doing refresh() here is better, - // to prevent that we forgot to refresh - // in SyncFrame. - refresh(); - - if(mf_movieSyncFrame()) - { - /* user did not hit anything. - * play next frame. - */ - if(mfmovie.mode == MFDISP_MOVIE_PLAYING) - { - if(!mf_movieNextFrame()) - { - STOP_MOVIE(); - - if(promptend == NA) - { - /* if we played to end, - * no need to prevent pressanykey(). - */ - flExit = 1, retval = 0; - } - } - } - else if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD) - { - if(mf_viewedAll()) - { - mfmovie.mode = MFDISP_MOVIE_NO; - mf_determinemaxdisps(MFNAV_PAGE, 0); - mf_forward(0); - } - else - { - if(!mfmovie.compat24) - PMORE_UINAV_FORWARDPAGE(); - else - mf_forward(22); - } - } - } else { - /* TODO simple navigation here? */ - - /* stop playing */ - if(mfmovie.mode == MFDISP_MOVIE_PLAYING) - { - STOP_MOVIE(); - if(promptend == NA) - { - flExit = 1, retval = READ_NEXT; - } - } - else if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD) - { - mfmovie.mode = MFDISP_MOVIE_NO; - mf_determinemaxdisps(MFNAV_PAGE, 0); - mf_forward(0); - } - } - continue; - } -#endif - - /* PRINT BOTTOM STATUS BAR */ -#ifdef DEBUG - if(debug) - { - /* in debug mode don't print ANSI codes - * because themselves are buggy. - */ - prints("L#%ld(w%ld,lp%ld) pmt=%d Dsp:%08X/%08X/%08X, " - "F:%08X/%08X(%d) tScr(%dx%d)", - mf.lineno, mf.wraplines, mf.lastpagelines, - promptend, - (unsigned int)mf.disps, - (unsigned int)mf.maxdisps, - (unsigned int)mf.dispe, - (unsigned int)mf.start, (unsigned int)mf.end, - (int)mf.len, - t_columns, - t_lines - ); - } - else -#endif - { - char *printcolor; - - char buf[256]; // orz - int prefixlen = 0; - int barlen = 0; - int postfix1len = 0, postfix2len = 0; - - int progress = - (int)((unsigned long)(mf.dispe-mf.start) * 100 / mf.len); - /* - * page determination is hard. - * should we use starting line, or finishing line? - */ - int nowpage = - (int)((mf.lineno + mf.dispedlines/2) / MFNAV_PAGE)+1; - int allpages = -1; /* unknown yet */ - if (mf.maxlinenoS >= 0) - { - allpages = - (int)((mf.maxlinenoS + mf.lastpagelines - - ((bpref.separator & MFDISP_SEP_WRAP) && - (fh.lines >= 0) ? 0:1)) / MFNAV_PAGE)+1; - if (mf.lineno >= mf.maxlinenoS || nowpage > allpages) - nowpage = allpages; - /* - nowpage = - (int)((mf.lineno + mf.dispedlines-2) / MFNAV_PAGE)+1 ; - */ - } - /* why -2 and -1? - * because we want to determine by nav_page, - * and mf.dispedlines is based on disp_page (nav_page+1) - * mf.lastpagelines is based on nav_page - */ - - if(mf_viewedAll()) - printcolor = ANSI_COLOR(37;44); - else if (mf_viewedNone()) - printcolor = ANSI_COLOR(33;45); - else - printcolor = ANSI_COLOR(34;46); - - outs(ANSI_RESET); - outs(printcolor); - - if(bpref.oldstatusbar) - { - - prints(" ÂsÄý P.%d(%d%%) %s %-30.30s%s", - nowpage, - progress, - ANSI_COLOR(31;47), - "(h)" - ANSI_COLOR(30) "¨D§U " - ANSI_COLOR(31) "¡÷¡õ[PgUp][", - "PgDn][Home][End]" - ANSI_COLOR(30) "´å¼Ð²¾°Ê " - ANSI_COLOR(31) "¡ö[q]" - ANSI_COLOR(30) "µ²§ô "); - - } else { - - if(allpages >= 0) - sprintf(buf, - " ÂsÄý ²Ä %1d/%1d ¶ (%3d%%) ", - nowpage, - allpages, - progress - ); - else - sprintf(buf, - " ÂsÄý ²Ä %1d ¶ (%3d%%) ", - nowpage, - progress - ); - outs(buf); prefixlen += strlen(buf); - - outs(ANSI_COLOR(1;30;47)); - - if(override_msg) - { - buf[0] = 0; - if(override_attr) outs(override_attr); - snprintf(buf, sizeof(buf), override_msg); - RESET_OVERRIDE_MSG(); - } - else - if(mf.xpos > 0) - { - snprintf(buf, sizeof(buf), - " Åã¥Ü½d³ò: %d~%d Äæ¦ì, %02d~%02d ¦æ", - (int)mf.xpos+1, - (int)(mf.xpos + t_columns-(mf.trunclines ? 2 : 1)), - (int)(mf.lineno + 1), - (int)(mf.lineno + mf.dispedlines) - ); - } else { - snprintf(buf, sizeof(buf), - " ¥Ø«eÅã¥Ü: ²Ä %02d~%02d ¦æ", - (int)(mf.lineno + 1), - (int)(mf.lineno + mf.dispedlines) - ); - } - - outs(buf); prefixlen += strlen(buf); - - postfix1len = 12; // check msg below - postfix2len = 10; - if(mf_viewedAll()) postfix1len = 17; - - if (prefixlen + postfix1len + postfix2len + 1 > t_columns) - { - postfix1len = 0; - if (prefixlen + postfix1len + postfix2len + 1 > t_columns) - postfix2len = 0; - } - barlen = t_columns - 1 - postfix1len - postfix2len - prefixlen; - - while(barlen-- > 0) - outc(' '); - - if(postfix1len > 0) - outs( - mf_viewedAll() ? - ANSI_COLOR(0;31;47)"(y)" ANSI_COLOR(30) "¦^«H" - ANSI_COLOR(31) "(X/%)" ANSI_COLOR(30) "±À¤å " - : - ANSI_COLOR(0;31;47) "(h)" - ANSI_COLOR(30) "«öÁ仡©ú " - ); - if(postfix2len > 0) - outs( - ANSI_COLOR(0;31;47) "¡ö[q]" - ANSI_COLOR(30) "Â÷¶} " - ); - } - outs(ANSI_RESET); - FORCE_CLRTOEOL(); - } - - /* igetch() will do refresh(); */ - ch = igetch(); - switch (ch) { - /* -------------- NEW EXITING KEYS ------------------ */ -#ifdef RET_DOREPLY - case 'r': case 'R': - flExit = 1, retval = RET_DOREPLY; - break; - case 'Y': case 'y': - flExit = 1, retval = RET_DOREPLYALL; - break; -#endif -#ifdef RET_DORECOMMEND - // recommend - case '%': - case 'X': - flExit = 1, retval = RET_DORECOMMEND; - break; -#endif -#ifdef RET_DOQUERYINFO - case 'Q': // info query interface - flExit = 1, retval = RET_DOQUERYINFO; - break; -#endif -#ifdef RET_DOSYSOPEDIT - case 'E': - flExit = 1, retval = RET_DOSYSOPEDIT; - break; -#endif -#ifdef RET_DOCHESSREPLAY - case 'z': - flExit = 1, retval = RET_DOCHESSREPLAY; - break; -#endif -#ifdef RET_COPY2TMP - case Ctrl('T'): - flExit = 1, retval = RET_COPY2TMP; - break; -#endif -#ifdef RET_SELECTBRD - case 's': - flExit = 1, retval = RET_SELECTBRD; - break; -#endif - /* ------------------ EXITING KEYS ------------------ */ - case 'A': - flExit = 1, retval = AUTHOR_PREV; - break; - case 'a': - flExit = 1, retval = AUTHOR_NEXT; - break; - case 'F': case 'f': - flExit = 1, retval = READ_NEXT; - break; - case 'B': case 'b': - flExit = 1, retval = READ_PREV; - break; - case KEY_LEFT: - flExit = 1, retval = FULLUPDATE; - break; - case 'q': - flExit = 1, retval = FULLUPDATE; - break; - - /* from Kaede, thread reading */ - case ']': - case '+': - flExit = 1, retval = RELATE_NEXT; - break; - case '[': - case '-': - flExit = 1, retval = RELATE_PREV; - break; - case '=': - flExit = 1, retval = RELATE_FIRST; - break; - /* ------------------ NAVIGATION KEYS ------------------ */ - /* Simple Navigation */ - case 'k': case 'K': - mf_backward(1); - break; - case 'j': case 'J': - PMORE_UINAV_FORWARDLINE(); - break; - - case Ctrl('F'): - case KEY_PGDN: - PMORE_UINAV_FORWARDPAGE(); - break; - case Ctrl('B'): - case KEY_PGUP: - mf_backward(MFNAV_PAGE); - break; - - case '0': - case 'g': - case KEY_HOME: - mf_goTop(); - break; - case '$': - case 'G': - case KEY_END: - mf_goBottom(); - -#ifdef PMORE_ACCURATE_WRAPEND - /* allright. in design of pmore, - * it's possible that when user navigates to file end, - * a wrapped line made nav not 100%. - */ - mf_display(); - invalidate = 0; - - if(!mf_viewedAll()) - { - /* one more try. */ - mf_goBottom(); - invalidate = 1; - } -#endif - break; - - /* Compound Navigation */ - case '.': - if(mf.xpos == 0) - mf.xpos ++; - mf.xpos ++; - break; - case ',': - if(mf.xpos > 0) - mf.xpos --; - break; - case '\t': - case '>': - //if(mf.xpos == 0 || mf.trunclines) - mf.xpos = (mf.xpos/8+1)*8; - break; - /* acronym form shift-tab, ^[[Z */ - /* however some terminals does not send that. */ - case KEY_STAB: - case '<': - mf.xpos = (mf.xpos/8-1)*8; - if(mf.xpos < 0) mf.xpos = 0; - break; - case '\r': - case '\n': - case KEY_DOWN: - if (mf_viewedAll() || - (promptend == 2 && (ch == '\r' || ch == '\n'))) - flExit = 1, retval = READ_NEXT; - else - PMORE_UINAV_FORWARDLINE(); - break; - - case ' ': - if (mf_viewedAll()) - flExit = 1, retval = READ_NEXT; - else - PMORE_UINAV_FORWARDPAGE(); - break; - case KEY_RIGHT: - if(mf_viewedAll()) - promptend = 0, flExit = 1, retval = 0; - else - { - /* if mf.xpos > 0, widenav mode. */ - /* because we have other keys to do so, - * disable it now. - */ - /* - if(mf.trunclines > 0) - { - if(mf.xpos == 0) - mf.xpos++; - mf.xpos++; - } - else if (mf.xpos == 0) - */ - PMORE_UINAV_FORWARDPAGE(); - } - break; - - case KEY_UP: - if(mf_viewedNone()) - flExit = 1, retval = READ_PREV; - else - mf_backward(1); - break; - case Ctrl('H'): - if(mf_viewedNone()) - flExit = 1, retval = READ_PREV; - else - mf_backward(MFNAV_PAGE); - break; - - case 't': - if (mf_viewedAll()) - flExit = 1, retval = RELATE_NEXT; - else - PMORE_UINAV_FORWARDPAGE(); - break; - /* ------------------ SEARCH KEYS ------------------ */ - case '/': - { - char sbuf[81] = ""; - char ans[4] = "n"; - - if(sr.search_str) { - free(sr.search_str); - sr.search_str = NULL; - } - - getdata(b_lines - 1, 0, PMORE_MSG_SEARCH_KEYWORD, sbuf, - 40, DOECHO); - - if (sbuf[0]) { - if (getdata(b_lines - 1, 0, "°Ï¤À¤j¤p¼g(Y/N/Q)? [N] ", - ans, sizeof(ans), LCECHO) && *ans == 'y') - sr.cmpfunc = strncmp; - else if (*ans == 'q') - sbuf[0] = 0; - else - sr.cmpfunc = strncasecmp; - } - sr.len = strlen(sbuf); - if(sr.len) sr.search_str = (unsigned char*)strdup(sbuf); - mf_search(MFSEARCH_FORWARD); - MFDISP_DIRTY(); - } - break; - case 'n': - mf_search(MFSEARCH_FORWARD); - break; - case 'N': - mf_search(MFSEARCH_BACKWARD); - break; - /* ------------------ SPECIAL KEYS ------------------ */ - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - case ';': case ':': - { - char buf[16] = ""; - int i = 0; - int pageMode = (ch != ':'); - if (ch >= '1' && ch <= '9') - buf[0] = ch, buf[1] = 0; - - pmore_clrtoeol(b_lines-1, 0); - getdata_buf(b_lines-1, 0, - (pageMode ? - "¸õ¦Ü¦¹¶(Yn§ï«ü©w¦æ¼Æ½Ð¦bµ²§À¥[.): " : - "¸õ¦Ü¦¹¦æ: "), - buf, 8, DOECHO); - if(buf[0]) { - i = atoi(buf); - if(buf[strlen(buf)-1] == '.') - pageMode = 0; - if(i-- > 0) - mf_goto(i * (pageMode ? MFNAV_PAGE : 1)); - } - MFDISP_DIRTY(); - } - break; - - case 'h': case 'H': case KEY_F1: - case '?': - // help - show_help(pmore_help); - MFDISP_DIRTY(); - break; - -#ifdef PMORE_NOTIFY_NEWPREF - //let's be backward compatible! - case 'l': - case 'w': - case 'W': - case '|': - vmsg("³oÓ«öÁä¤w¾ã¦X¶i·sªº³]©w (o) ¤F"); - break; - -#endif // PMORE_NOTIFY_NEWPREF - - case '\\': // everyone loves backslash, let's keep it. - pmore_QuickRawModePref(); - MFDISP_DIRTY(); - break; - - case 'o': - pmore_Preference(); - MFDISP_DIRTY(); - break; - -#if defined(USE_BBSLUA) && defined(RET_DOBBSLUA) - case 'P': - vmsg("«D±`©êºp¡ABBS-Lua ªº¼öÁä¤w§ï¬° L ¡A½Ð§ï«ö L"); - break; - - case 'L': - case 'l': - flExit = 1, retval = RET_DOBBSLUA; - break; -#endif - -#ifdef PMORE_USE_ASCII_MOVIE - case 'p': - /* play ascii movie again - */ - if(mfmovie.mode == MFDISP_MOVIE_YES) - { - RESET_MOVIE(); - mfmovie.mode = MFDISP_MOVIE_PLAYING; - mf_determinemaxdisps(0, 0); // display until last line - /* it is said that it's better not to go top. */ - // mf_goTop(); - mf_movieNextFrame(); - MFDISP_DIRTY(); - } - else if (mfmovie.mode == MFDISP_MOVIE_NO) - { - static char buf[10]="1"; - //move(b_lines-1, 0); - - /* - * TODO scan current page to confirm if this is a new style movie - */ - pmore_clrtoeol(b_lines-1, 0); - getdata_buf(b_lines - 1, 0, - PMORE_MSG_MOVIE_PLAYOLD_GETTIME, - buf, 8, LCECHO); - - if(buf[0]) - { - float nf = 0; - nf = atof(buf); // sscanf(buf, "%f", &nf); - RESET_MOVIE(); - - mfmovie.mode = MFDISP_MOVIE_PLAYING_OLD; - mf_float2tv(nf, &mfmovie.frameclk); - mfmovie.compat24 = 0; - /* are we really going to start? check termsize! */ - if (t_lines != 24) - { - char ans[4]; - pmore_clrtoeol(b_lines-1, 0); - getdata(b_lines - 1, 0, - PMORE_MSG_MOVIE_PLAYOLD_AS24L, - ans, 3, LCECHO); - if(ans[0] == 'n') - mfmovie.compat24 = 0; - else - mfmovie.compat24 = 1; - } - mf_determinemaxdisps(0, 0); // display until last line - MFDISP_DIRTY(); - } - } - break; -#endif - -#ifdef DEBUG - case 'd': - debug = !debug; - MFDISP_DIRTY(); - break; -#endif - - } - /* DO NOT DO ANYTHING HERE. NOT SAFE RIGHT NOW. */ - } - - mf_detach(); - if (retval == 0 && promptend) { - pressanykey(); - clear(); - } else - outs(reset_color); - - REENTRANT_RESTORE(); - return retval; -} - -// ---------------------------------------------------- Preference and Help - -static void -pmore_prefEntry( - int isel, - const char *key, int szKey, - const char *text,int szText, - const char* options) -{ - int i = 23; - // print key/text - outs(" " ANSI_COLOR(1;31)); //OPTATTR_NORMAL_KEY); - if (szKey < 0) szKey = strlen(key); - if (szKey > 0) outs_n(key, szKey); - outs(ANSI_RESET " "); - if (szText < 0) szText = strlen(text); - if (szText > 0) outs_n(text, szText); - - i -= szKey + szText; - if (i < 0) i+= 20; // one more chance - while (i-- > 0) outc(' '); - - // print options - i = 0; - while (*options) - { - if (*options == '\t') - { - // blank option, skip it. - i++, options++; - continue; - } - - if (i > 0) - outs(ANSI_COLOR(1;30) " |" ANSI_RESET); //OPTATTR_BAR " | " ANSI_RESET); - - // test if option has hotkey - if (*options && *options != '\t' && - *(options+1) && *(options+1) == '.') - { - // found hotkey - outs(ANSI_COLOR(1;31)); //OPTATTR_NORMAL_KEY); - outc(*options); - outs(ANSI_RESET); - options +=2; - } - - if (i == isel) - { - outs(ANSI_COLOR(1;36) "*");// OPTATTR_SELECTED); - } - else - outc(' '); - - while (*options && *options != '\t') - outc(*options++); - - outs(ANSI_RESET); - - if (*options) - i++, options ++; - } - outc('\n'); -} - -void -pmore_PromptBar(const char *caption, int shadow) -{ - int i = 0; - - if (shadow) - { - outs(ANSI_COLOR(0;1;30)); - for(i = 0; i+2 < t_columns ; i+=2) - outs("¢b"); - outs(ANSI_RESET "\n"); - } - else - i = t_columns -2; - - outs(ANSI_COLOR(7)); - outs(caption); - for(i -= strlen(caption); i > 0; i--) - outs(" "); - outs(ANSI_RESET "\n"); -} - -void -pmore_QuickRawModePref() -{ - int ystart = b_lines -2; - -#ifdef HAVE_GRAYOUT - grayout(0, ystart-1, GRAYOUT_DARK); -#endif // HAVE_GRAYOUT - - while(1) - { - move(ystart, 0); - clrtobot(); - pmore_PromptBar(PMORE_MSG_PREF_TITLE_QRAW, 0); - - // list options - pmore_prefEntry(bpref.rawmode, - "\\", 1, "¦â±mÅã¥Ü¤è¦¡:", -1, - "1.¹w³]®æ¦¡¤Æ¤º®e\t2.ì©lANSI±±¨î½X\t3.¯Â¤å¦r"); - - switch(vmsg("½Ð½Õ¾ã³]©w (1-3 ¥iª½±µ¿ï©w¡A\\¥i¤Á´«) ©Î¨ä¥¦¥ô·NÁäµ²§ô¡C")) - { - case '\\': - bpref.rawmode = (bpref.rawmode+1) % MFDISP_RAW_MODES; - break; - case '1': - bpref.rawmode = MFDISP_RAW_NA; - return; - case '2': - bpref.rawmode = MFDISP_RAW_NOANSI; - return; - case '3': - bpref.rawmode = MFDISP_RAW_PLAIN; - return; - case KEY_LEFT: - if (bpref.rawmode > 0) bpref.rawmode --; - break; - case KEY_RIGHT: - if (bpref.rawmode < MFDISP_RAW_MODES-1) bpref.rawmode ++; - break; - default: - return; - } - } -} - -void -pmore_Preference() -{ - int ystart = b_lines - 9; - // TODO even better pref navigation, like arrow keys - // static int lastkey = '\\'; // default key - -#ifdef HAVE_GRAYOUT - grayout(0, ystart-1, GRAYOUT_DARK); -#endif // HAVE_GRAYOUT - - while (1) - { - move(ystart, 0); - clrtobot(); - pmore_PromptBar(PMORE_MSG_PREF_TITLE, 1); - outs("\n"); - - // list options - pmore_prefEntry(bpref.rawmode, - "\\", 1, "¦â±mÅã¥Ü¤è¦¡:", -1, - "¹w³]®æ¦¡¤Æ¤º®e\tì©lANSI±±¨î½X\t¯Â¤å¦r"); - - pmore_prefEntry(bpref.wrapmode, - "w", 1, "Â_¦æ¤è¦¡:", -1, - "ª½±µºI¦æ\t¦Û°ÊÂ_¦æ"); - - pmore_prefEntry(bpref.wrapindicator, - "m", 1, "Â_¦æ²Å¸¹:", -1, - "¤£Åã¥Ü\tÅã¥Ü"); - - pmore_prefEntry(bpref.separator, - "l", 1, "¤å³¹¼ÐÀY¤À¹j½u:", -1, - "µL\t³æ¦æ\t\t¶Ç²Î¤À¹j½u¥[ªÅ¦æ"); - - pmore_prefEntry(bpref.oldstatusbar, - "t", 1, "¶Ç²Îª¬ºA¦C»PÂ_¦æ¤è¦¡: ", -1, - "°±¥Î\t±Ò¥Î"); - - switch(vmsg("½Ð½Õ¾ã³]©w©Î¨ä¥¦¥ô·NÁäµ²§ô¡C")) - { - case '\\': - case '|': - bpref.rawmode = (bpref.rawmode+1) % MFDISP_RAW_MODES; - break; - case 'w': - bpref.wrapmode = (bpref.wrapmode+1) % MFDISP_WRAP_MODES; - break; - case 'm': - bpref.wrapindicator = !bpref.wrapindicator; - break; - case 'l': - // there's no MFDISP_SEP_WRAP only mode. - if (++bpref.separator == MFDISP_SEP_WRAP) - bpref.separator ++; - bpref.separator %= MFDISP_SEP_MODES; - break; - case 't': - bpref.oldwrapmode = !bpref.oldwrapmode; - bpref.oldstatusbar = !bpref.oldstatusbar; - break; - - default: - // finished settings - return; - } - } -} - -void -pmore_Help() -{ - clear(); - stand_title("pmore ¨Ï¥Î»¡©ú"); - vmsg(""); -} - -// ---------------------------------------------------- Extra modules - -#ifdef PMORE_USE_ASCII_MOVIE -void -mf_float2tv(float f, struct timeval *ptv) -{ - if(f < MOVIE_MIN_FRAMECLK) - f = MOVIE_MIN_FRAMECLK; - if (f > MOVIE_MAX_FRAMECLK) - f = MOVIE_MAX_FRAMECLK; - - ptv->tv_sec = (long) f; - ptv->tv_usec = (f - (long)f) * MOVIE_SECOND_U; -} - -int -mf_str2float(unsigned char *p, unsigned char *end, float *pf) -{ - char buf[16] = {0}; - int cbuf = 0; - - /* process time */ - while ( p < end && - cbuf < sizeof(buf)-1 && - (isdigit(*p) || *p == '.' || *p == '+' || *p == '-')) - buf[cbuf++] = *p++; - - if (!cbuf) - return 0; - - buf[cbuf] = 0; - *pf = atof(buf); - - return 1; -} - -/* - * maybe you can use add_io or you have other APIs in - * your I/O system, but we'll do it here. - * override if you have better methods. - */ -int -pmore_wait_key(struct timeval *ptv, int dorefresh) -{ - int sel = 0; - fd_set readfds; - int c = 0; - - if (dorefresh) - refresh(); - - do { - // if already something in queue, - // detemine if ok to break. - while ( num_in_buf() > 0) - { - if (!mf_movieMaskedInput((c = igetch()))) - return c; - } - - // wait for real user interaction - FD_ZERO(&readfds); - FD_SET(0, &readfds); - -#ifdef STATINC - STATINC(STAT_SYSSELECT); -#endif - sel = select(1, &readfds, NULL, NULL, ptv); - - // if select() stopped by other interrupt, - // do it again. - if (sel < 0 && errno == EINTR) - continue; - - // if (sel > 0), try to read. - // note: there may be more in queue. - // will be processed at next loop. - if (sel > 0 && !mf_movieMaskedInput((c = igetch()))) - return c; - - } while (sel > 0); - - // now, maybe something for read (sel > 0) - // or time out (sel == 0) - // or weird error (sel < 0) - - // sync clock(now) if timeout. - if (sel == 0) - syncnow(); - - return (sel == 0) ? 0 : 1; -} - -// type : 1 = option selection, 0 = normal -int -mf_moviePromptPlaying(int type) -{ - int w = t_columns - 1; - // s may change to anykey... - const char *s = PMORE_MSG_MOVIE_PLAYING; - - if (override_msg) - { - // we must warn user about something... - move(type ? b_lines-2 : b_lines-1, 0); // clrtoeol? - outs(ANSI_RESET); - if (override_attr) outs(override_attr); - w -= strlen(override_msg); - outs(override_msg); - while(w-- > 0) outc(' '); - - outs(ANSI_RESET ANSI_CLRTOEND); - RESET_OVERRIDE_MSG(); - w = t_columns -1; - } - - move(type ? b_lines-1 : b_lines, 0); // clrtoeol? - - if (type) - { - outs(ANSI_RESET ANSI_COLOR(1;34;47)); - s = " >> ½Ð¿é¤J¿ï¶µ: (¤¬°Ê¦¡°Êµe¼½©ñ¤¤¡A¥i«ö q ©Î Ctrl-C ¤¤Â_)"; - } - else if (mfmovie.interactive) - { - outs(ANSI_RESET ANSI_COLOR(1;34;47)); - s = PMORE_MSG_MOVIE_INTERACTION_PLAYING; - } else { - outs(ANSI_RESET ANSI_COLOR(1;30;47)); - } - - w -= strlen(s); outs(s); - - while(w-- > 0) outc(' '); outs(ANSI_RESET ANSI_CLRTOEND); - if (type) - { - move(b_lines, 0); - clrtoeol(); - } - - return 1; -} - -// return = printed characters -int -mf_moviePromptOptions( - int isel, int maxsel, - int key, - unsigned char *text, unsigned int szText) -{ - unsigned char *s = text; - int printlen = 0; - // determine if we need separator - if (maxsel) - { - outs(OPTATTR_BAR "|" ); - printlen += 1; - } - - // highlight if is selected - if (isel == maxsel) - outs(OPTATTR_SELECTED_KEY); - else - outs(OPTATTR_NORMAL_KEY); - - outc(' '); printlen ++; - - if (key > ' ' && key < 0x80) // isprint(key)) - { - outc(key); - printlen += 1; - } else { - // named keys - printlen += 2; - - if (key == KEY_UP) outs("¡ô"); - else if (key == KEY_LEFT) outs("¡ö"); - else if (key == KEY_DOWN) outs("¡õ"); - else if (key == KEY_RIGHT) outs("¡÷"); - else if (key == KEY_PGUP) { outs("PgUp"); printlen += 2; } - else if (key == KEY_PGDN) { outs("PgDn"); printlen += 2; } - else if (key == KEY_HOME) { outs("Home"); printlen += 2; } - else if (key == KEY_END) { outs("End"); printlen ++; } - else if (key == KEY_INS) { outs("Ins"); printlen ++; } - else if (key == KEY_DEL) { outs("Del"); printlen ++; } - else if (key == '\b') { outs("¡öBS"); printlen += 2; } - // else if (key == MOVIE_KEY_ANY) // same as default - else printlen -= 2; - } - - // check text: we don't allow special char. - if (text && szText && text[0]) - { - while (s < text + szText && *s > ' ') - { - s++; - } - szText = s - text; - } - else - { - // default option text - text = (unsigned char*)"¡¸"; - szText = ustrlen(text); - } - - if (szText) - { - if (isel == maxsel) - outs(OPTATTR_SELECTED); - else - outs(OPTATTR_NORMAL); - outs_n((char*)text, szText); - printlen += szText; - } - - outc(' '); printlen ++; - - // un-highlight - if (isel == maxsel) - outs(OPTATTR_NORMAL); - - return printlen; -} - -int -mf_movieNamedKey(int c) -{ - switch (c) - { - case 'u': return KEY_UP; - case 'd': return KEY_DOWN; - case 'l': return KEY_LEFT; - case 'r': return KEY_RIGHT; - - case 'b': return '\b'; - - case 'H': return KEY_HOME; - case 'E': return KEY_END; - case 'I': return KEY_INS; - case 'D': return KEY_DEL; - case 'P': return KEY_PGUP; - case 'N': return KEY_PGDN; - - case 'a': return MOVIE_KEY_ANY; - default: - break; - } - return 0; -} - -int mf_movieIsSystemBreak(int c) -{ - return (c == 'q' || c == 'Q' || c == Ctrl('C')) - ? 1 : 0; -} - -int -mf_movieMaskedInput(int c) -{ - unsigned char *p = mfmovie.optkeys; - - if (!p) - return 0; - - // some keys cannot be masked - if (mf_movieIsSystemBreak(c)) - return 0; - - // treat BS and DEL as same one - if (c == MOVIE_KEY_BS2) - c = '\b'; - - // general look up - while (p < mf.end && *p && *p != '\n' && *p != '#') - { - if (*p == '@' && mf.end - p > 1 - && isalnum(*(p+1))) // named key - { - p++; - - // special: 'a' masks all - if (*p == 'a' || mf_movieNamedKey(*p) == c) - return 1; - } else { - if ((int)*p == c) - return 1; - } - p++; - } - return 0; -} - -unsigned char * -mf_movieFrameHeader(unsigned char *p, unsigned char *end) -{ - // ANSI has ESC_STR [8m as "Conceal" but - // not widely supported, even PieTTY. - // So let's go back to fixed format... - static char *patHeader = "==" ESC_STR "[30;40m^L"; - static char *patHeader2= ESC_STR "[30;40m^L"; // patHeader + 2; // "==" - // static char *patHeader3= ESC_STR "[m^L"; - static size_t szPatHeader = 12; // strlen(patHeader); - static size_t szPatHeader2 = 10; // strlen(patHeader2); - // static size_t szPatHeader3 = 5; // strlen(patHeader3); - - size_t sz = end - p; - - if (sz < 1) return NULL; - if(*p == 12) // ^L - return p+1; - - if (sz < 2) return NULL; - if( *p == '^' && - *(p+1) == 'L') - return p+2; - - // Add more frame headers - - /* // *[m seems not so common, skip. - if (sz < szPatHeader3) return NULL; - if (memcmp(p, patHeader3, szPatHeader3) == 0) - return p + szPatHeader3; - */ - - if (sz < szPatHeader2) return NULL; - if (memcmp(p, patHeader2, szPatHeader2) == 0) - return p + szPatHeader2; - - if (sz < szPatHeader) return NULL; - if (memcmp(p, patHeader, szPatHeader) == 0) - return p + szPatHeader; - - return NULL; -} - -int -mf_movieGotoNamedFrame(const unsigned char *name, const unsigned char *end) -{ - const unsigned char *p = name; - size_t sz = 0; - - // resolve name first - while (p < end && isalnum(*p)) - p++; - sz = p - name; - - if (sz < 1) return 0; - - // now search entire file for frame - - mf_goTop(); - - do - { - if ((p = mf_movieFrameHeader(mf.disps, mf.end)) == NULL || - *p != ':') - continue; - - // got some frame. let's check the name - p++; - if (mf.end - p < sz) - continue; - - // check: target of p must end. - if (mf.end -p > sz && - isalnum(*(p+sz))) - continue; - - if (memcmp(p, name, sz) == 0) - return 1; - - } while (mf_forward(1) > 0); - return 0; -} - -int -mf_movieGotoFrame(int fno, int relative) -{ - if (!relative) - mf_goTop(); - else if (fno > 0) - mf_forward(1); - // for absolute, fno = 1..N - - if (fno > 0) - { - // move forward - do { - while (mf_movieFrameHeader(mf.disps, mf.end) == NULL) - { - if (mf_forward(1) < 1) - return 0; - } - // found frame. - if (--fno > 0) - mf_forward(1); - } while (fno > 0); - } else { - // backward - // XXX check if we reached head? - while (fno < 0) - { - do { - if (mf_backward(1) < 1) - return 0; - } while (mf_movieFrameHeader(mf.disps, mf.end) == NULL); - fno ++; - } - } - return 1; -} - -int -mf_parseOffsetCmd( - unsigned char *s, unsigned char *end, - int base) -{ - // return is always > 0, or base. - int v = 0; - - if (s >= end) - return base; - - v = atoi((char*)s); - - if (*s == '+' || *s == '-') - { - // relative format - v = base + v; - } else if (isdigit(*s)) { - // absolute format - } else { - // error format? - v = 0; - } - - if (v <= 0) - v = base; - return v; -} - -int -mf_movieExecuteOffsetCmd(unsigned char *s, unsigned char *end) -{ - // syntax: type[+-]offset - // - // type: l(line), f(frame), p(page). - // +-: if empty, absolute. if assigned, relative. - // offset: is 1 .. N for all cases - - int curr = 0, newno = 0; - - switch(*s) - { - case 'p': - // by page - curr = (mf.lineno / MFDISP_PAGE) + 1; - newno = mf_parseOffsetCmd(s+1, end, curr); -#ifdef DEBUG - vmsgf("page: %d -> %d\n", curr, newno); -#endif // DEBUG - // prevent endless loop - if (newno == curr) - return 0; - - return mf_goto((newno -1) * MFDISP_PAGE); - - case 'l': - // by lines - curr = mf.lineno + 1; - newno = mf_parseOffsetCmd(s+1, end, curr); -#ifdef DEBUG - vmsgf("line: %d -> %d\n", curr, newno); -#endif // DEBUG - // prevent endless loop - if (newno == curr) - return 0; - - return mf_goto(newno-1); - - case 'f': - // by frame [optimized] - if (++s >= end) - return 0; - - curr = 0; - newno = atoi((char*)s); - if (*s == '+' || *s == '-') // relative - { - curr = 1; - if (newno == 0) - return 0; - } else { - // newno starts from 1 - if (newno <= 0) - return 0; - } - return mf_movieGotoFrame(newno, curr); - - case ':': - // by names - return mf_movieGotoNamedFrame(s+1, end); - - default: - // not supported yet - break; - } - return 0; -} - - -int -mf_movieOptionHandler(unsigned char *opt, unsigned char *end) -{ - // format: #time#key1,cmd,text1#key2,cmd,text2# - // if key is empty, use auto-increased key. - // if cmd is empty, invalid. - // if text is empty, display key only or hide if time is assigned. - - int ient = 0; - unsigned char *pkey = NULL, *cmd = NULL, *text = NULL; - unsigned int szCmd = 0, szText = 0; - unsigned char *p = opt; - int key = 0; - float optclk = -1.0f; // < 0 means infinite wait - struct timeval tv; - - int isel = 0, c = 0, maxsel = 0, selected = 0; - int newOpt = 1; - int hideOpts = 0; - int promptlen = 0; - - // TODO handle line length - // TODO restrict option size - - // set up timer (opt points to optional time now) - do { - p = opt; - while ( p < end && - (isdigit(*p) || *p == '+' || *p == '-' || *p == '.') ) - p++; - - // if no number, abort. - if (p == opt || (p < end && *p != '#')) break; - - // p looks like valid timer now - if (mf_str2float(opt, p, &optclk)) - { - // conversion failed. - if (optclk == 0) - optclk = -1.0f; - } - - // point opt to new var after #. - opt = p + 1; - break; - - } while (1); - - // UI Selection - do { - // do c test here because we need parser to help us - // finding the selection - if (c == '\r' || c == '\n' || c == ' ') - { - selected = 1; - } - - newOpt = 1; - promptlen = 0; - - // parse (key,frame,text) - for ( p = opt, ient = 0, maxsel = 0, - key = '0'; // default command - p < end && *p != '\n'; p++) - { - if (newOpt) - { - // prepare for next loop - pkey = p; - cmd = text = NULL; - szCmd = szText = 0; - ient = 0; - newOpt = 0; - } - - // calculation of fields - if (*p == ',' || *p == '#') - { - switch (++ient) - { - // case 0 is already processed. - case 1: - cmd = p+1; - break; - - case 2: - text = p+1; - szCmd = p - cmd; - break; - - case 3: - szText = p - text; - - default: - // unknown parameters - break; - } - } - - // ready to parse one option - if (*p == '#') - { - newOpt = 1; - - // first, fix pointers - if (szCmd == 0 || *cmd == ',' || *cmd == '#') - { cmd = NULL; szCmd = 0; } - - // quick abort if option is invalid. - if (!cmd) - continue; - - if (szText == 0 || *text == ',' || *text == '#') - { text = NULL; szText = 0; } - - // assign key - if (*pkey == ',' || *pkey == '#') - key++; - else - { - // named key? - int nk = 0; - - // handle special case @a (all) here - - if (*pkey == '@' && - ++ pkey < end && - (nk = mf_movieNamedKey(*pkey))) - { - key = nk; - } else { - key = *pkey; - } - // warning: pkey may be changed after this. - } - - // calculation complete. - - // print option - if (!hideOpts && maxsel == 0 && text == NULL) - { - hideOpts = 1; - mf_moviePromptPlaying(0); - // prevent more hideOpt test - } - - if (!hideOpts) - { - // print header - if (maxsel == 0) - { - pmore_clrtoeol(b_lines-1, 0); - mf_moviePromptPlaying(1); - } - - promptlen += mf_moviePromptOptions( - isel, maxsel, key, - text, szText); - } - - // handle selection - if (c == key || - (key == MOVIE_KEY_ANY && c != 0)) - { - // hotkey pressed - selected = 1; - isel = maxsel; - } - - maxsel ++; - - // parse complete. - // test if this item is selected. - if (selected && isel == maxsel - 1) - break; - } - } - - if (selected || maxsel == 0) - break; - - // finish the selection bar - if (!hideOpts && maxsel > 0) - { - int iw = 0; - for (iw = 0; iw + promptlen < t_columns-1; iw++) - outc(' '); - outs(ANSI_RESET ANSI_CLRTOEND); - } - - // wait for input - if (optclk > 0) - { - // timed interaction - - // disable optkeys to allow masked input - unsigned char *tmpopt = mfmovie.optkeys; - mfmovie.optkeys = NULL; - - mf_float2tv(optclk, &tv); - c = pmore_wait_key(&tv, 1); - mfmovie.optkeys = tmpopt; - - // if timeout, drop. - if (!c) - return 0; - } else { - // infinite wait - c = igetch(); - } - - // parse keyboard input - if (mf_movieIsSystemBreak(c)) - { - // cannot be masked, - // also force stop of playback - STOP_MOVIE(); - vmsg(PMORE_MSG_MOVIE_INTERACTION_STOPPED); - return 0; - } - - // treat BS and DEL as same one - if (c == MOVIE_KEY_BS2) - c = '\b'; - - // standard navigation keys. - if (mf_movieMaskedInput(c)) - continue; - - // these keys can be masked - if (c == KEY_LEFT || c == KEY_UP) - { - if (isel > 0) isel --; - } - else if (c == KEY_RIGHT || c == KEY_TAB || c == KEY_DOWN) - { - if (isel < maxsel-1) isel ++; - } - else if (c == KEY_HOME) - { - isel = 0; - } - else if (c == KEY_END) - { - isel = maxsel -1; - } - - } while ( !selected ); - - // selection is made now. - outs(ANSI_RESET); // required because options bar may be not closed - pmore_clrtoeol(b_lines, 0); - -#ifdef DEBUG - prints("selection: %d\n", isel); - igetch(); -#endif - - // Execute Selection - if (!cmd || !szCmd) - return 0; - - return mf_movieExecuteOffsetCmd(cmd, cmd+szCmd); -} - -/* - * mf_movieSyncFrame: - * wait until synchronization, and flush break key (if any). - * return meaning: - * I've got synchronized. - * If no (user breaks), return 0 - */ -int mf_movieSyncFrame() -{ - if (mfmovie.pause) - { - int c = 0; - mfmovie.pause = 0; - c = vmsg(PMORE_MSG_MOVIE_PAUSE); - if (mf_movieIsSystemBreak(c)) - return 0; - return 1; - } - else if (mfmovie.options) - { - unsigned char *opt = mfmovie.options; - mfmovie.options = NULL; - mf_movieOptionHandler(opt, mf.end); - return 1; - } - else if (mfmovie.synctime.tv_sec > 0) - { - /* synchronize world timeline model */ - struct timeval dv; - gettimeofday(&dv, NULL); - dv.tv_sec = mfmovie.synctime.tv_sec - dv.tv_sec; - if(dv.tv_sec < 0) - return 1; - dv.tv_usec = mfmovie.synctime.tv_usec - dv.tv_usec; - if(dv.tv_usec < 0) { - dv.tv_sec --; - dv.tv_usec += MOVIE_SECOND_U; - } - if(dv.tv_sec < 0) - return 1; - - return !pmore_wait_key(&dv, 0); - } else { - /* synchronize each frame clock model */ - /* because Linux will change the timeval passed to select, - * let's use a temp value here. - */ - struct timeval dv = mfmovie.frameclk; - return !pmore_wait_key(&dv, 0); - } -} - -#define MOVIECMD_SKIP_ALL(p,end) \ - while (p < end && *p && *p != '\n') \ - { p++; } \ - -unsigned char * -mf_movieProcessCommand(unsigned char *p, unsigned char *end) -{ - for (; p < end && *p != '\n'; p++) - { - if (*p == 'S') { - // SYNCHRONIZATION - gettimeofday(&mfmovie.synctime, NULL); - // S can take other commands - } - else if (*p == 'E') - { - // END - STOP_MOVIE(); - // MFDISP_SKIPCURLINE(); - MOVIECMD_SKIP_ALL(p,end); - return p; - } - else if (*p == 'P') - { - // PAUSE - mfmovie.pause = 1; - // MFDISP_SKIPCURLINE(); - MOVIECMD_SKIP_ALL(p,end); - return p; - - } - else if (*p == 'G') - { - // GOTO - // Gt+-n,t+-n,t+-n (random select one) - // jump +-n of type(l,p,f) - - // random select, if multiple - unsigned char *pe = p; - unsigned int igs = 0; - - for (pe = p ; pe < end && *pe && - *pe > ' ' && *pe < 0x80 - ; pe ++) - if (*pe == ',') igs++; - - if (igs) - { - // make random - igs = random() % (igs+1); - - for (pe = p ; igs > 0 && pe < end && *pe && - *pe > ' ' && *pe < 0x80 - ; pe ++) - if (*pe == ',') igs--; - - if (pe != p) - p = pe-1; - } - - mf_movieExecuteOffsetCmd(p+1, end); - MOVIECMD_SKIP_ALL(p,end); - return p; - } - else if (*p == ':') - { - // NAMED - // :name: - // name allows alnum only - p++; - // TODO check isalnum p? - - // :name can accept trailing commands - while (p < end && *p != '\n' && *p != ':') - p++; - - if (*p == ':') p++; - - // continue will increase p - p--; - continue; - } - else if (*p == 'K') - { - // Reserve Key for interactive usage. - // Currently only K#...# format is supported. - if (p+2 < end && *(p+1) == '#') - { - p += 2; - mfmovie.optkeys = p; - mfmovie.interactive = 1; - - // K#..# can accept trailing commands - while (p < end && *p != '\n' && *p != '#') - p++; - - // if empty, set optkeys to NULL? - if (mfmovie.optkeys == p) - mfmovie.optkeys = NULL; - - if (*p == '#') p++; - - // continue will increase p - p--; - continue; - } - MOVIECMD_SKIP_ALL(p,end); - return p; - } - else if (*p == '#') - { - // OPTIONS - // #key1,frame1,text1#key2,frame2,text2# - mfmovie.options = p+1; - mfmovie.interactive = 1; - // MFDISP_SKIPCURLINE(); - MOVIECMD_SKIP_ALL(p,end); - return p; - } - else if (*p == 'O') - { - // OLD compatible mode - // = -> compat24 - // - -> ? - // == -> ? - p++; - if (p >= end) - return end; - if (*p == '=') - { - mfmovie.mode = MFDISP_MOVIE_PLAYING_OLD; - mfmovie.compat24 = 1; - p++; - } - // MFDISP_SKIPCURLINE(); - return p+1; - } - else if (*p == 'L') - { - // LOOP - // Lm,n - // m times to backward n - break; - } - else - { - // end of known control codes - break; - } - } - return p; -} - -int -mf_movieNextFrame() -{ - while (1) - { - unsigned char *p = mf_movieFrameHeader(mf.disps, mf.end); - - if(p) - { - float nf = 0; - unsigned char *odisps = mf.disps; - - /* process leading */ - p = mf_movieProcessCommand(p, mf.end); - - // disps may change after commands - if (mf.disps != odisps) - { - // commands changing location must - // support at least one frame pause - // to allow user break - struct timeval tv; - mf_float2tv(MOVIE_MIN_FRAMECLK, &tv); - - if (pmore_wait_key(&tv, 0)) - { - STOP_MOVIE(); - return 0; - } - continue; - } - - /* process time */ - if (mf_str2float(p, mf.end, &nf)) - { - mf_float2tv(nf, &mfmovie.frameclk); - } - - if(mfmovie.synctime.tv_sec > 0) - { - mfmovie.synctime.tv_usec += mfmovie.frameclk.tv_usec; - mfmovie.synctime.tv_sec += mfmovie.frameclk.tv_sec; - mfmovie.synctime.tv_sec += mfmovie.synctime.tv_usec / MOVIE_SECOND_U; - mfmovie.synctime.tv_usec %= MOVIE_SECOND_U; - } - - if (mfmovie.mode != MFDISP_MOVIE_PLAYING_OLD) - mf_forward(1); - - return 1; - } - - if (mf_forward(1) <= 0) - break; - } - - return 0; -} -#endif - -/* vim:sw=4:ts=8:expandtab:nofoldenable - */ diff --git a/mbbsd/random.c b/mbbsd/random.c deleted file mode 100644 index dd369c41..00000000 --- a/mbbsd/random.c +++ /dev/null @@ -1,711 +0,0 @@ -#ifdef __dietlibc__ -/* - Copyright (C) 1995 Free Software Foundation - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* - Copyright (C) 1983 Regents of the University of California. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE.*/ - -/* - * This is derived from the Berkeley source: - * @(#)random.c 5.5 (Berkeley) 7/6/88 - * It was reworked for the GNU C Library by Roland McGrath. - * Rewritten to be reentrant by Ulrich Drepper, 1995 - */ - -#include <errno.h> -#include <limits.h> -#include <stddef.h> -#include <stdlib.h> -struct random_data - { - int32_t *fptr; /* Front pointer. */ - int32_t *rptr; /* Rear pointer. */ - int32_t *state; /* Array of state values. */ - int rand_type; /* Type of random number generator. */ - int rand_deg; /* Degree of random number generator. */ - int rand_sep; /* Distance between front and rear. */ - int32_t *end_ptr; /* Pointer behind state table. */ - }; -int __random_r (struct random_data *buf, int32_t *result); - - - -/* An improved random number generation package. In addition to the standard - rand()/srand() like interface, this package also has a special state info - interface. The initstate() routine is called with a seed, an array of - bytes, and a count of how many bytes are being passed in; this array is - then initialized to contain information for random number generation with - that much state information. Good sizes for the amount of state - information are 32, 64, 128, and 256 bytes. The state can be switched by - calling the setstate() function with the same array as was initialized - with initstate(). By default, the package runs with 128 bytes of state - information and generates far better random numbers than a linear - congruential generator. If the amount of state information is less than - 32 bytes, a simple linear congruential R.N.G. is used. Internally, the - state information is treated as an array of longs; the zeroth element of - the array is the type of R.N.G. being used (small integer); the remainder - of the array is the state information for the R.N.G. Thus, 32 bytes of - state information will give 7 longs worth of state information, which will - allow a degree seven polynomial. (Note: The zeroth word of state - information also has some other information stored in it; see setstate - for details). The random number generation technique is a linear feedback - shift register approach, employing trinomials (since there are fewer terms - to sum up that way). In this approach, the least significant bit of all - the numbers in the state table will act as a linear feedback shift register, - and will have period 2^deg - 1 (where deg is the degree of the polynomial - being used, assuming that the polynomial is irreducible and primitive). - The higher order bits will have longer periods, since their values are - also influenced by pseudo-random carries out of the lower bits. The - total period of the generator is approximately deg*(2**deg - 1); thus - doubling the amount of state information has a vast influence on the - period of the generator. Note: The deg*(2**deg - 1) is an approximation - only good for large deg, when the period of the shift register is the - dominant factor. With deg equal to seven, the period is actually much - longer than the 7*(2**7 - 1) predicted by this formula. */ - - - -/* For each of the currently supported random number generators, we have a - break value on the amount of state information (you need at least this many - bytes of state info to support this random number generator), a degree for - the polynomial (actually a trinomial) that the R.N.G. is based on, and - separation between the two lower order coefficients of the trinomial. */ - -/* Linear congruential. */ -#define TYPE_0 0 -#define BREAK_0 8 -#define DEG_0 0 -#define SEP_0 0 - -/* x**7 + x**3 + 1. */ -#define TYPE_1 1 -#define BREAK_1 32 -#define DEG_1 7 -#define SEP_1 3 - -/* x**15 + x + 1. */ -#define TYPE_2 2 -#define BREAK_2 64 -#define DEG_2 15 -#define SEP_2 1 - -/* x**31 + x**3 + 1. */ -#define TYPE_3 3 -#define BREAK_3 128 -#define DEG_3 31 -#define SEP_3 3 - -/* x**63 + x + 1. */ -#define TYPE_4 4 -#define BREAK_4 256 -#define DEG_4 63 -#define SEP_4 1 - - -/* Array versions of the above information to make code run faster. - Relies on fact that TYPE_i == i. */ - -#define MAX_TYPES 5 /* Max number of types above. */ - -struct random_poly_info -{ - int seps[MAX_TYPES]; - int degrees[MAX_TYPES]; -}; - -static const struct random_poly_info random_poly_info = -{ - { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }, - { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 } -}; - - - - -/* Initialize the random number generator based on the given seed. If the - type is the trivial no-state-information type, just remember the seed. - Otherwise, initializes state[] based on the given "seed" via a linear - congruential generator. Then, the pointers are set to known locations - that are exactly rand_sep places apart. Lastly, it cycles the state - information a given number of times to get rid of any initial dependencies - introduced by the L.C.R.N.G. Note that the initialization of randtbl[] - for default usage relies on values produced by this routine. */ -int -__srandom_r (seed, buf) - unsigned int seed; - struct random_data *buf; -{ - int type; - int32_t *state; - long int i; - long int word; - int32_t *dst; - int kc; - - if (buf == NULL) - goto fail; - type = buf->rand_type; - if ((unsigned int) type >= MAX_TYPES) - goto fail; - - state = buf->state; - /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ - if (seed == 0) - seed = 1; - state[0] = seed; - if (type == TYPE_0) - goto done; - - dst = state; - word = seed; - kc = buf->rand_deg; - for (i = 1; i < kc; ++i) - { - /* This does: - state[i] = (16807 * state[i - 1]) % 2147483647; - but avoids overflowing 31 bits. */ - long int hi = word / 127773; - long int lo = word % 127773; - word = 16807 * lo - 2836 * hi; - if (word < 0) - word += 2147483647; - *++dst = word; - } - - buf->fptr = &state[buf->rand_sep]; - buf->rptr = &state[0]; - kc *= 10; - while (--kc >= 0) - { - int32_t discard; - (void) __random_r (buf, &discard); - } - - done: - return 0; - - fail: - return -1; -} - - -/* Initialize the state information in the given array of N bytes for - future random number generation. Based on the number of bytes we - are given, and the break values for the different R.N.G.'s, we choose - the best (largest) one we can and set things up for it. srandom is - then called to initialize the state information. Note that on return - from srandom, we set state[-1] to be the type multiplexed with the current - value of the rear pointer; this is so successive calls to initstate won't - lose this information and will be able to restart with setstate. - Note: The first thing we do is save the current state, if any, just like - setstate so that it doesn't matter when initstate is called. - Returns a pointer to the old state. */ -int -__initstate_r (seed, arg_state, n, buf) - unsigned int seed; - char *arg_state; - size_t n; - struct random_data *buf; -{ - int type; - int degree; - int separation; - int32_t *state; - - if (buf == NULL) - goto fail; - - if (n >= BREAK_3) - type = n < BREAK_4 ? TYPE_3 : TYPE_4; - else if (n < BREAK_1) - { - if (n < BREAK_0) - { - __set_errno (EINVAL); - goto fail; - } - type = TYPE_0; - } - else - type = n < BREAK_2 ? TYPE_1 : TYPE_2; - - degree = random_poly_info.degrees[type]; - separation = random_poly_info.seps[type]; - - buf->rand_type = type; - buf->rand_sep = separation; - buf->rand_deg = degree; - state = &((int32_t *) arg_state)[1]; /* First location. */ - /* Must set END_PTR before srandom. */ - buf->end_ptr = &state[degree]; - - buf->state = state; - - __srandom_r (seed, buf); - - state[-1] = TYPE_0; - if (type != TYPE_0) - state[-1] = (buf->rptr - state) * MAX_TYPES + type; - - return 0; - - fail: - __set_errno (EINVAL); - return -1; -} - - -/* Restore the state from the given state array. - Note: It is important that we also remember the locations of the pointers - in the current state information, and restore the locations of the pointers - from the old state information. This is done by multiplexing the pointer - location into the zeroth word of the state information. Note that due - to the order in which things are done, it is OK to call setstate with the - same state as the current state - Returns a pointer to the old state information. */ -int -__setstate_r (arg_state, buf) - char *arg_state; - struct random_data *buf; -{ - int32_t *new_state = 1 + (int32_t *) arg_state; - int type; - int old_type; - int32_t *old_state; - int degree; - int separation; - - if (arg_state == NULL || buf == NULL) - goto fail; - - old_type = buf->rand_type; - old_state = buf->state; - if (old_type == TYPE_0) - old_state[-1] = TYPE_0; - else - old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type; - - type = new_state[-1] % MAX_TYPES; - if (type < TYPE_0 || type > TYPE_4) - goto fail; - - buf->rand_deg = degree = random_poly_info.degrees[type]; - buf->rand_sep = separation = random_poly_info.seps[type]; - buf->rand_type = type; - - if (type != TYPE_0) - { - int rear = new_state[-1] / MAX_TYPES; - buf->rptr = &new_state[rear]; - buf->fptr = &new_state[(rear + separation) % degree]; - } - buf->state = new_state; - /* Set end_ptr too. */ - buf->end_ptr = &new_state[degree]; - - return 0; - - fail: - __set_errno (EINVAL); - return -1; -} - - -/* If we are using the trivial TYPE_0 R.N.G., just do the old linear - congruential bit. Otherwise, we do our fancy trinomial stuff, which is the - same in all the other cases due to all the global variables that have been - set up. The basic operation is to add the number at the rear pointer into - the one at the front pointer. Then both pointers are advanced to the next - location cyclically in the table. The value returned is the sum generated, - reduced to 31 bits by throwing away the "least random" low bit. - Note: The code takes advantage of the fact that both the front and - rear pointers can't wrap on the same call by not testing the rear - pointer if the front one has wrapped. Returns a 31-bit random number. */ - -int -__random_r (buf, result) - struct random_data *buf; - int32_t *result; -{ - int32_t *state; - - if (buf == NULL || result == NULL) - goto fail; - - state = buf->state; - - if (buf->rand_type == TYPE_0) - { - int32_t val = state[0]; - val = ((state[0] * 1103515245) + 12345) & 0x7fffffff; - state[0] = val; - *result = val; - } - else - { - int32_t *fptr = buf->fptr; - int32_t *rptr = buf->rptr; - int32_t *end_ptr = buf->end_ptr; - int32_t val; - - val = *fptr += *rptr; - /* Chucking least random bit. */ - *result = (val >> 1) & 0x7fffffff; - ++fptr; - if (fptr >= end_ptr) - { - fptr = state; - ++rptr; - } - else - { - ++rptr; - if (rptr >= end_ptr) - rptr = state; - } - buf->fptr = fptr; - buf->rptr = rptr; - } - return 0; - - fail: - __set_errno (EINVAL); - return -1; -} - -/* Copyright (C) 1995 Free Software Foundation - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* - * This is derived from the Berkeley source: - * @(#)random.c 5.5 (Berkeley) 7/6/88 - * It was reworked for the GNU C Library by Roland McGrath. - * Rewritten to use reentrant functions by Ulrich Drepper, 1995. - */ - -/* - Copyright (C) 1983 Regents of the University of California. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE.*/ - -#include <limits.h> -#include <stddef.h> -#include <stdlib.h> - - -/* An improved random number generation package. In addition to the standard - rand()/srand() like interface, this package also has a special state info - interface. The initstate() routine is called with a seed, an array of - bytes, and a count of how many bytes are being passed in; this array is - then initialized to contain information for random number generation with - that much state information. Good sizes for the amount of state - information are 32, 64, 128, and 256 bytes. The state can be switched by - calling the setstate() function with the same array as was initialized - with initstate(). By default, the package runs with 128 bytes of state - information and generates far better random numbers than a linear - congruential generator. If the amount of state information is less than - 32 bytes, a simple linear congruential R.N.G. is used. Internally, the - state information is treated as an array of longs; the zeroth element of - the array is the type of R.N.G. being used (small integer); the remainder - of the array is the state information for the R.N.G. Thus, 32 bytes of - state information will give 7 longs worth of state information, which will - allow a degree seven polynomial. (Note: The zeroth word of state - information also has some other information stored in it; see setstate - for details). The random number generation technique is a linear feedback - shift register approach, employing trinomials (since there are fewer terms - to sum up that way). In this approach, the least significant bit of all - the numbers in the state table will act as a linear feedback shift register, - and will have period 2^deg - 1 (where deg is the degree of the polynomial - being used, assuming that the polynomial is irreducible and primitive). - The higher order bits will have longer periods, since their values are - also influenced by pseudo-random carries out of the lower bits. The - total period of the generator is approximately deg*(2**deg - 1); thus - doubling the amount of state information has a vast influence on the - period of the generator. Note: The deg*(2**deg - 1) is an approximation - only good for large deg, when the period of the shift register is the - dominant factor. With deg equal to seven, the period is actually much - longer than the 7*(2**7 - 1) predicted by this formula. */ - - - -/* For each of the currently supported random number generators, we have a - break value on the amount of state information (you need at least this many - bytes of state info to support this random number generator), a degree for - the polynomial (actually a trinomial) that the R.N.G. is based on, and - separation between the two lower order coefficients of the trinomial. */ - -/* Linear congruential. */ -#define TYPE_0 0 -#define BREAK_0 8 -#define DEG_0 0 -#define SEP_0 0 - -/* x**7 + x**3 + 1. */ -#define TYPE_1 1 -#define BREAK_1 32 -#define DEG_1 7 -#define SEP_1 3 - -/* x**15 + x + 1. */ -#define TYPE_2 2 -#define BREAK_2 64 -#define DEG_2 15 -#define SEP_2 1 - -/* x**31 + x**3 + 1. */ -#define TYPE_3 3 -#define BREAK_3 128 -#define DEG_3 31 -#define SEP_3 3 - -/* x**63 + x + 1. */ -#define TYPE_4 4 -#define BREAK_4 256 -#define DEG_4 63 -#define SEP_4 1 - - -/* Array versions of the above information to make code run faster. - Relies on fact that TYPE_i == i. */ - -#define MAX_TYPES 5 /* Max number of types above. */ - - -/* Initially, everything is set up as if from: - initstate(1, randtbl, 128); - Note that this initialization takes advantage of the fact that srandom - advances the front and rear pointers 10*rand_deg times, and hence the - rear pointer which starts at 0 will also end up at zero; thus the zeroth - element of the state information, which contains info about the current - position of the rear pointer is just - (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */ - -static int32_t randtbl[DEG_3 + 1] = - { - TYPE_3, - - -1726662223, 379960547, 1735697613, 1040273694, 1313901226, - 1627687941, -179304937, -2073333483, 1780058412, -1989503057, - -615974602, 344556628, 939512070, -1249116260, 1507946756, - -812545463, 154635395, 1388815473, -1926676823, 525320961, - -1009028674, 968117788, -123449607, 1284210865, 435012392, - -2017506339, -911064859, -370259173, 1132637927, 1398500161, - -205601318, - }; - - -static struct random_data unsafe_state = - { -/* FPTR and RPTR are two pointers into the state info, a front and a rear - pointer. These two pointers are always rand_sep places aparts, as they - cycle through the state information. (Yes, this does mean we could get - away with just one pointer, but the code for random is more efficient - this way). The pointers are left positioned as they would be from the call: - initstate(1, randtbl, 128); - (The position of the rear pointer, rptr, is really 0 (as explained above - in the initialization of randtbl) because the state table pointer is set - to point to randtbl[1] (as explained below).) */ - - .fptr = &randtbl[SEP_3 + 1], - .rptr = &randtbl[1], - -/* The following things are the pointer to the state information table, - the type of the current generator, the degree of the current polynomial - being used, and the separation between the two pointers. - Note that for efficiency of random, we remember the first location of - the state information, not the zeroth. Hence it is valid to access - state[-1], which is used to store the type of the R.N.G. - Also, we remember the last location, since this is more efficient than - indexing every time to find the address of the last element to see if - the front and rear pointers have wrapped. */ - - .state = &randtbl[1], - - .rand_type = TYPE_3, - .rand_deg = DEG_3, - .rand_sep = SEP_3, - - .end_ptr = &randtbl[sizeof (randtbl) / sizeof (randtbl[0])] -}; - -/* POSIX.1c requires that there is mutual exclusion for the `rand' and - `srand' functions to prevent concurrent calls from modifying common - data. */ - -/* Initialize the random number generator based on the given seed. If the - type is the trivial no-state-information type, just remember the seed. - Otherwise, initializes state[] based on the given "seed" via a linear - congruential generator. Then, the pointers are set to known locations - that are exactly rand_sep places apart. Lastly, it cycles the state - information a given number of times to get rid of any initial dependencies - introduced by the L.C.R.N.G. Note that the initialization of randtbl[] - for default usage relies on values produced by this routine. */ -void -__srandom (x) - unsigned int x; -{ - (void) __srandom_r (x, &unsafe_state); -} - - -/* Initialize the state information in the given array of N bytes for - future random number generation. Based on the number of bytes we - are given, and the break values for the different R.N.G.'s, we choose - the best (largest) one we can and set things up for it. srandom is - then called to initialize the state information. Note that on return - from srandom, we set state[-1] to be the type multiplexed with the current - value of the rear pointer; this is so successive calls to initstate won't - lose this information and will be able to restart with setstate. - Note: The first thing we do is save the current state, if any, just like - setstate so that it doesn't matter when initstate is called. - Returns a pointer to the old state. */ -char * -__initstate (seed, arg_state, n) - unsigned int seed; - char *arg_state; - size_t n; -{ - int32_t *ostate; - - - ostate = &unsafe_state.state[-1]; - - __initstate_r (seed, arg_state, n, &unsafe_state); - - - return (char *) ostate; -} - - -/* Restore the state from the given state array. - Note: It is important that we also remember the locations of the pointers - in the current state information, and restore the locations of the pointers - from the old state information. This is done by multiplexing the pointer - location into the zeroth word of the state information. Note that due - to the order in which things are done, it is OK to call setstate with the - same state as the current state - Returns a pointer to the old state information. */ -char * -__setstate (arg_state) - char *arg_state; -{ - int32_t *ostate; - - - ostate = &unsafe_state.state[-1]; - - if (__setstate_r (arg_state, &unsafe_state) < 0) - ostate = NULL; - - - return (char *) ostate; -} - - -/* If we are using the trivial TYPE_0 R.N.G., just do the old linear - congruential bit. Otherwise, we do our fancy trinomial stuff, which is the - same in all the other cases due to all the global variables that have been - set up. The basic operation is to add the number at the rear pointer into - the one at the front pointer. Then both pointers are advanced to the next - location cyclically in the table. The value returned is the sum generated, - reduced to 31 bits by throwing away the "least random" low bit. - Note: The code takes advantage of the fact that both the front and - rear pointers can't wrap on the same call by not testing the rear - pointer if the front one has wrapped. Returns a 31-bit random number. */ - -long int -__random (void) -{ - int32_t retval; - - - (void) __random_r (&unsafe_state, &retval); - - - return retval; -} - -long int glibc_random(void) { return __random(); } -void glibc_srandom(unsigned int seed) { __srandom(seed); } -char *glibc_initstate(unsigned int seed, char *state, size_t n) { return __initstate(seed,state,n); } -char *glibc_setstate(char *state) { return __setstate(state); } -#endif diff --git a/mbbsd/read.c b/mbbsd/read.c deleted file mode 100644 index 97621725..00000000 --- a/mbbsd/read.c +++ /dev/null @@ -1,1371 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -static int headers_size = 0; -static fileheader_t *headers = NULL; -static int last_line; // PTT: last_line ´å¼Ð¥i«üªº³Ì«á¤@Ó - -#include <sys/mman.h> - -/* ----------------------------------------------------- */ -/* Tag List ¼ÐÅÒ */ -/* ----------------------------------------------------- */ -static TagItem *TagList = NULL; /* ascending list */ - -/** - * @param locus - * @return void - */ -void -UnTagger(int locus) -{ - if (locus > TagNum || TagNum <= 0) - return; - - TagNum--; - - if (TagNum > locus) - memmove(&TagList[locus], &TagList[locus + 1], - (TagNum - locus) * sizeof(TagItem)); -} - -int -Tagger(time4_t chrono, int recno, int mode) -{ - int head, tail, posi = 0, comp; - - if(TagList == NULL) { - TagList = malloc(sizeof(TagItem)*(MAXTAGS+1)); - } - - for (head = 0, tail = TagNum - 1, comp = 1; head <= tail;) { - posi = (head + tail) >> 1; - comp = TagList[posi].chrono - chrono; - if (!comp) { - break; - } else if (comp < 0) { - head = posi + 1; - } else { - tail = posi - 1; - } - } - - if (mode == TAG_NIN) { - if (!comp && recno) /* µ´¹ïÄYÂÔ¡G³s recno ¤@°_¤ñ¹ï */ - comp = recno - TagList[posi].recno; - return comp; - - } - if (!comp) { - if (mode != TAG_TOGGLE || TagNum <= 0) - return NA; - - TagNum--; - memmove(&TagList[posi], &TagList[posi + 1], - (TagNum - posi) * sizeof(TagItem)); - } else if (TagNum < MAXTAGS) { - TagItem *tagp; - - memmove(&TagList[head+1], &TagList[head], sizeof(TagItem)*(TagNum-head)); - tagp = &TagList[head]; - tagp->chrono = chrono; - tagp->recno = recno; - TagNum++; - } else { - bell(); - return 0; /* full */ - } - return YEA; -} - -#if 0 -static void -EnumTagName(char *fname, int locus) /* unused */ -{ - snprintf(fname, sizeof(fname), "M.%d.A", (int)TagList[locus].chrono); -} -#endif - -void -EnumTagFhdr(fileheader_t * fhdr, char *direct, int locus) -{ - get_record(direct, fhdr, sizeof(fileheader_t), TagList[locus].recno); -} - -/* -1 : ¨ú®ø */ -/* 0 : single article */ -/* ow: whole tag list */ - -int -AskTag(const char *msg) -{ - int num; - - num = TagNum; - switch (getans("¡» %s A)¤å³¹ T)¼Ð°O Q)uit?", msg)) { - case 'q': - num = -1; - break; - case 'a': - num = 0; - } - return num; -} - - -#include <sys/mman.h> - -#define BATCH_SIZE 65536 - -static char * -f_map(const char *fpath, int *fsize) -{ - int fd, size; - struct stat st; - char *map; - - if ((fd = open(fpath, O_RDONLY)) < 0) - return (char *)-1; - - if (fstat(fd, &st) || !S_ISREG(st.st_mode) || (size = st.st_size) <= 0) { - close(fd); - return (char *)-1; - } - map = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - close(fd); - *fsize = size; - return map; -} - - -static int -TagThread(const char *direct) -{ - int fsize, count; - char *title, *fimage; - fileheader_t *head, *tail; - - fimage = f_map(direct, &fsize); - if (fimage == (char *)-1) - return DONOTHING; - - head = (fileheader_t *) fimage; - tail = (fileheader_t *) (fimage + fsize); - count = 0; - do { - count++; - title = subject(head->title); - if (!strncmp(currtitle, title, TTLEN)) { - if (!Tagger(atoi(head->filename + 2), count, TAG_INSERT)) - break; - } - } while (++head < tail); - - munmap(fimage, fsize); - return FULLUPDATE; -} - - -int -TagPruner(int bid) -{ - boardheader_t *bp=NULL; - assert(bid >= 0); /* bid == 0 means in mailbox */ - if (bid){ - bp = getbcache(bid); - if (strcmp(bp->brdname, GLOBAL_SECURITY) == 0) - return DONOTHING; - } - if (TagNum && ((currstat != READING) || (currmode & MODE_BOARD))) { - if (getans("§R°£©Ò¦³¼Ð°O[N]?") != 'y') - return READ_REDRAW; -#ifdef SAFE_ARTICLE_DELETE - if(bp && !(currmode & MODE_DIGEST) && bp->nuser>30 ) - safe_delete_range(currdirect, 0, 0); - else -#endif - delete_range(currdirect, 0, 0); - TagNum = 0; - if (bid) - setbtotal(bid); - else if(currstat == RMAIL) - setupmailusage(); - - return NEWDIRECT; - } - return DONOTHING; -} - - -/* ----------------------------------------------------- */ -/* cursor & reading record position control */ -/* ----------------------------------------------------- */ -keeploc_t * -getkeep(const char *s, int def_topline, int def_cursline) -{ - /* ¬°¬Ù°O¾ÐÅé, ¥BÁקK malloc/free ¤£¦¨¹ï, getkeep ³Ì¦n¤£n malloc, - * ¥u°O s ªº hash È, - * fvn1a-32bit collision ¾÷²v¬ù¤p©ó¤Q¸U¤À¤§¤@ */ - /* 쥻¨Ï¥Î link list, ¥i¬O¤@¤è±·|³y¦¨ malloc/free ¤£¦¨¹ï, - * ¤@¤è± size ¤p, malloc space overhead ´N°ª, ¦]¦¹§ï¦¨ link block, - * ¥H KEEPSLOT ¬°¤@Ó block ªº link list. - * ¥u¦³²Ä¤@Ó block ¥i¯à¨Sº¡. */ - /* TODO LRU recycle? ³Â·Ð¦b©ó§O³B¥i¯à§â keeploc_t pointer °OµÛ... */ -#define KEEPSLOT 10 - struct keepsome { - unsigned char used; - keeploc_t arr[KEEPSLOT]; - struct keepsome *next; - }; - static struct keepsome preserv_keepblock; - static struct keepsome *keeplist = &preserv_keepblock; - struct keeploc_t *p; - unsigned key=StringHash(s); - int i; - - if (def_cursline >= 0) { - struct keepsome *kl=keeplist; - while(kl) { - for(i=0; i<kl->used; i++) - if(key == kl->arr[i].hashkey) { - p = &kl->arr[i]; - if (p->crs_ln < 1) - p->crs_ln = 1; - return p; - } - kl=kl->next; - } - } else - def_cursline = -def_cursline; - - if(keeplist->used==KEEPSLOT) { - struct keepsome *kl; - kl = (struct keepsome*)malloc(sizeof(struct keepsome)); - memset(kl, 0, sizeof(struct keepsome)); - kl->next = keeplist; - keeplist = kl; - } - p = &keeplist->arr[keeplist->used]; - keeplist->used++; - p->hashkey = key; - p->top_ln = def_topline; - p->crs_ln = def_cursline; - return p; -} - -void -fixkeep(const char *s, int first) -{ - keeploc_t *k; - - k = getkeep(s, 1, 1); - if (k->crs_ln >= first) { - k->crs_ln = (first == 1 ? 1 : first - 1); - k->top_ln = (first < 11 ? 1 : first - 10); - } -} - -/* calc cursor pos and show cursor correctly */ -static int -cursor_pos(keeploc_t * locmem, int val, int from_top, int isshow) -{ - int top=locmem->top_ln; - if (!last_line){ - cursor_show(3 , 0); - return DONOTHING; - } - if (val > last_line) - val = last_line; - if (val <= 0) - val = 1; - if (val >= top && val < top + headers_size) { - if(isshow){ - if(locmem->crs_ln >= top) - cursor_clear(3 + locmem->crs_ln - top, 0); - cursor_show(3 + val - top, 0); - } - locmem->crs_ln = val; - return DONOTHING; - } - locmem->top_ln = val - from_top; - if (locmem->top_ln <= 0) - locmem->top_ln = 1; - locmem->crs_ln = val; - return isshow ? PARTUPDATE : HEADERS_RELOAD; -} - -/** - * ®Ú¾Ú stypen ¿ï¾Ü¤W/¤U¤@½g¤å³¹ - * - * @param locmem ¥Î¨Ó¦s¦b¬Y¬ÝªO´å¼Ð¦ì¸mªº structure¡C - * @param stypen ´å¼Ð²¾°Êªº¤èªk - * CURSOR_FIRST, CURSOR_NEXT, CURSOR_PREV: - * »P´å¼Ð¥Ø«e¦ì¸mªº¤å³¹¦P¼ÐÃD ªº ²Ä¤@½g/¤U¤@½g/«e¤@½g ¤å³¹¡C - * RELATE_FIRST, RELATE_NEXT, RELATE_PREV: - * »P¥Ø«e¥¿¾\Ūªº¤å³¹¦P¼ÐÃD ªº ²Ä¤@½g/¤U¤@½g/«e¤@½g ¤å³¹¡C - * NEWPOST_NEXT, NEWPOST_PREV: - * ¤U¤@Ó/«e¤@Ó thread ªº²Ä¤@½g¡C - * AUTHOR_NEXT, AUTHOR_PREV: - * XXX ³o¥\¯à¥Ø«e¦n¹³¨S¥Î¨ì? - * - * @return ·sªº´å¼Ð¦ì¸m - */ -static int -thread(const keeploc_t * locmem, int stypen) -{ - fileheader_t fh; - int pos = locmem->crs_ln, jump = THREAD_SEARCH_RANGE, new_ln; - int fd = -1, amatch = -1; - int step = (stypen & RS_FORWARD) ? 1 : -1; - char *key; - - if(locmem->crs_ln==0) - return locmem->crs_ln; - - STATINC(STAT_THREAD); - if (stypen & RS_AUTHOR) - key = headers[pos - locmem->top_ln].owner; - else if (stypen & RS_CURRENT) - key = subject(currtitle); - else - key = subject(headers[pos - locmem->top_ln].title ); - - for( new_ln = pos + step ; - new_ln > 0 && new_ln <= last_line && --jump > 0; - new_ln += step ) { - - int rk = - get_record_keep(currdirect, &fh, sizeof(fileheader_t), new_ln, &fd); - - if(fd < 0 || rk < 0) - { - new_ln = pos; - break; - } - - if( stypen & RS_TITLE ){ - if( stypen & RS_FIRST ){ - if( !strncmp(fh.title, key, PROPER_TITLE_LEN) ) - break; - else if( !strncmp(&fh.title[4], key, PROPER_TITLE_LEN) ) { - amatch = new_ln; - jump = THREAD_SEARCH_RANGE; - /* ·í·j´M¦P¥DÃD²Ä¤@½g, ³sÄò§ä¤£¨ì¦h¤Ö½g¤~°± */ - } - } - else if( !strncmp(subject(fh.title), key, PROPER_TITLE_LEN) ) - break; - } - else if( stypen & RS_NEWPOST ){ - if( strncmp(fh.title, "Re:", 3) ) - break; - } - else{ // RS_AUTHOR - if( strcmp(subject(fh.owner), key) == EQUSTR ) - break; - } - } - - if( fd != -1 ) - close(fd); - - if( jump <= 0 || new_ln <= 0 || new_ln > last_line ) - new_ln = (amatch == -1 ? pos : amatch); //didn't find - - return new_ln; -} - -#ifdef INTERNET_EMAIL -static void -mail_forward(const fileheader_t * fhdr, const char *direct, int mode) -{ - int i; - char buf[STRLEN]; - char *p; - - strlcpy(buf, direct, sizeof(buf)); - if ((p = strrchr(buf, '/'))) - *p = '\0'; - switch (i = doforward(buf, fhdr, mode)) { - case 0: - vmsg(msg_fwd_ok); - break; - case -1: - vmsg(msg_fwd_err1); - break; - case -2: -#ifndef DEBUG_FWDADDRERR - vmsg(msg_fwd_err2); -#endif - break; - case -4: - vmsg("«H½c¤wº¡"); - break; - default: - break; - } -} -#endif - -// return: 1 - found, 0 - fail. -inline static int -dbcs_strcasestr(const char* pool, const char *ptr) -{ -#if 0 - // old method - int len = strlen(ptr); - - while(*pool) - { - // FIXME ¥Î strncasecmp ÁÙ¬O·|¿ù - if(strncasecmp(pool, ptr, len) == 0) - return 1; - /* else */ - if(*pool < 0) - { - pool ++; - if(*pool == 0) - return 0; - } - pool ++; - } - return 0; - -#endif - - int i = 0, i2 = 0, found = 0, - szpool = strlen(pool), - szptr = strlen(ptr); - - for (i = 0; i <= szpool-szptr; i++) - { - found = 1; - - // compare szpool[i..szptr] with ptr - for (i2 = 0; i2 < szptr; i2++) - { - if (pool[i + i2] > 0) - { - // ascii - if (ptr[i2] < 0 || - tolower(ptr[i2]) != tolower(pool[i+i2])) - { - // printf("break on ascii (i=%d, i2=%d).\n", i, i2); - found = 0; - break; - } - } else { - // non-ascii - if (ptr[i2] != pool[i+i2] || - ptr[i2+1] != pool[i+i2+1]) - { - // printf("break on non-ascii (i=%d, i2=%d).\n", i, i2); - found = 0; - break; - } - i2 ++; - } - } - - if (found) break; - - // next iteration: if target is DBCS, skip one more byte. - if (pool[i] < 0) - i++; - } - return found; -} - -static int -select_read(const keeploc_t * locmem, int sr_mode) -{ -#define READSIZE 64 // 8192 / sizeof(fileheader_t) - time4_t filetime; - fileheader_t fhs[READSIZE]; - char newdirect[MAXPATHLEN]; - int first_select; - char genbuf[MAXPATHLEN], *p = strstr(currdirect, "SR."); - static int _mode = 0; - int reload, inc; - int len, fd, fr, i, count = 0, reference = 0; - int filemode; - /* selection condition */ - char keyword[TTLEN + 1] = ""; - int n_recommend = 0, n_money = 0; - - - if(locmem->crs_ln == 0) - return locmem->crs_ln; - - first_select = p==NULL; - - STATINC(STAT_SELECTREAD); - if(sr_mode & RS_AUTHOR) - { - if(!getdata(b_lines, 0, - currmode & MODE_SELECT ? "¼W¥[±ø¥ó §@ªÌ: ":"·j´M§@ªÌ: ", - keyword, IDLEN+1, LCECHO)) - return READ_REDRAW; - } - else if(sr_mode & RS_KEYWORD) - { - if(!getdata(b_lines, 0, - currmode & MODE_SELECT ? "¼W¥[±ø¥ó ¼ÐÃD: ":"·j´M¼ÐÃD: ", - keyword, TTLEN, DOECHO)) - return READ_REDRAW; -#ifdef KEYWORD_LOG - log_file("keyword_search_log", LOG_CREAT | LOG_VF, - "%s:%s\n", currboard, keyword); -#endif - } - else if(sr_mode & RS_KEYWORD_EXCLUDE) - { - if(!(currmode & MODE_SELECT) || - !getdata(b_lines, 0, "¼W¥[±ø¥ó ±Æ°£¼ÐÃD: ", - keyword, TTLEN, DOECHO)) - return READ_REDRAW; - } - else if (sr_mode & RS_RECOMMEND) - { - if(currstat == RMAIL || ( - !getdata(b_lines, 0, - (currmode & MODE_SELECT) ? - "¼W¥[±ø¥ó ±À¤å¼Æ: ": - "·j´M±À¤å¼Æ°ª©ó¦h¤Ö" -#ifndef OLDRECOMMEND - " (<0«h·j¼N¤å¼Æ) " -#endif // OLDRECOMMEND - "ªº¤å³¹: ", - keyword, 7, LCECHO) || (n_recommend = atoi(keyword)) == 0 )) - return READ_REDRAW; - } - else if (sr_mode & RS_MONEY) - { - if(currstat == RMAIL || ( - !getdata(b_lines, 0, - (currmode & MODE_SELECT) ? - "¼W¥[±ø¥ó ¤å³¹»ù®æ: ":"·j´M»ù®æ°ª©ó¦h¤Öªº¤å³¹: ", - keyword, 7, LCECHO) || (n_money = atoi(keyword)) <= 0 )) - return READ_REDRAW; - strcat(keyword, "M"); - } - else { - // Ptt: only once for these modes. - if(!first_select && _mode & sr_mode & (RS_TITLE | RS_NEWPOST | RS_MARK)) - return DONOTHING; - - if(sr_mode & RS_TITLE) { - fileheader_t *fh = &headers[locmem->crs_ln - locmem->top_ln]; - strcpy(keyword, subject(fh->title)); - } - } - - if(first_select) - _mode = sr_mode; - else - _mode |= sr_mode; - - snprintf(genbuf, sizeof(genbuf), "%s%X.%X.%X", - first_select ? "SR.":p, - sr_mode, (int)strlen(keyword), DBCS_StringHash(keyword)); - if( strlen(genbuf) > MAXPATHLEN - 50 ) - return READ_REDRAW; // avoid overflow - - if (currstat == RMAIL) - sethomefile(newdirect, cuser.userid, genbuf); - else - setbfile(newdirect, currboard, genbuf); - - filetime = dasht(newdirect); - count = dashs(newdirect) / sizeof(fileheader_t); - - if (currstat != RMAIL && currboard[0] && currbid > 0) - { - time4_t filecreate = dashc(newdirect); - boardheader_t *bp = getbcache(currbid); - assert(bp); - - if (bp->SRexpire) - { - if (bp->SRexpire > now) // invalid expire time. - bp->SRexpire = now; - - if (bp->SRexpire > filecreate) - filetime = -1; - } - } - - if(filetime<0 || now-filetime>60*60) { - reload = 1; - inc = 0; - } else if(now-filetime > 3*60) { - reload = 1; - inc = 1; - } else { - /* use cached data */ - reload = 0; - inc = 0; - } - - /* mark and recommend shouldn't incremental select */ - if(sr_mode & (RS_MARK | RS_RECOMMEND)) - inc = 0; - - if(reload) { - if( (fr = open(currdirect, O_RDONLY, 0)) != -1 ) { - if(inc) { - /* find incremental selection start point */ - int idx; - sprintf(fhs[0].filename, "X.%d", (int)filetime); - idx = getindex(currdirect, &fhs[0], 0); - if(idx<0) { - reference = -idx; - } else if(idx==0) { - inc = 0; - } else { - reference = idx; - } - } - if(inc) { - filemode = O_APPEND | O_RDWR; - } else { - filemode = O_CREAT | O_RDWR; - count = 0; - reference = 0; - } - - if( (fd = open(newdirect, filemode, 0600)) == -1 ) { - close(fr); - return READ_REDRAW; - } - - if(reference>0) - lseek(fr, reference*sizeof(fileheader_t), SEEK_SET); - -#ifdef DEBUG - vmsgf("search: %s", currdirect); -#endif - while( (len = read(fr, fhs, sizeof(fhs))) > 0 ){ - len /= sizeof(fileheader_t); - for( i = 0 ; i < len ; ++i ){ - reference++; - if( (sr_mode & RS_MARK) && - !(fhs[i].filemode & FILE_MARKED) ) - continue; - else if((sr_mode & RS_NEWPOST) && - !strncmp(fhs[i].title, "Re:", 3)) - continue; - else if((sr_mode & RS_AUTHOR) && - !dbcs_strcasestr(fhs[i].owner, keyword)) - continue; - else if((sr_mode & RS_KEYWORD) && - !dbcs_strcasestr(fhs[i].title, keyword)) - continue; - else if(sr_mode & RS_KEYWORD_EXCLUDE && - dbcs_strcasestr(fhs[i].title, keyword)) - continue; - else if((sr_mode & RS_TITLE) && - strcasecmp(subject(fhs[i].title), keyword)) - continue; - else if ((sr_mode & RS_RECOMMEND) && - (n_recommend > 0 ? - (fhs[i].recommend < n_recommend) : - (fhs[i].recommend > n_recommend) )) - continue; - /* please put money test in last */ - else if ((sr_mode & RS_MONEY) && - query_file_money(fhs+i) < n_money) - continue; - - if(first_select) { - fhs[i].multi.refer.flag = 1; - fhs[i].multi.refer.ref = reference; - } - ++count; - write(fd, &fhs[i], sizeof(fileheader_t)); - } - } // end while - close(fr); - ftruncate(fd, count*sizeof(fileheader_t)); - close(fd); - } - } - - if(count) { - strlcpy(currdirect, newdirect, sizeof(currdirect)); - currmode |= MODE_SELECT; - currsrmode |= sr_mode; - return NEWDIRECT; - } - return READ_REDRAW; -} - -static int newdirect_new_ln = -1; - -static int -i_read_key(const onekey_t * rcmdlist, keeploc_t * locmem, - int bid, int bottom_line) -{ - int mode = DONOTHING, num, new_top=10; - int ch, new_ln = locmem->crs_ln, lastmode = DONOTHING; - char direct[60]; - static char default_ch = 0; - - do { - if( (mode = cursor_pos(locmem, new_ln, new_top, default_ch ? 0 : 1)) - != DONOTHING ) - return mode; - - if( !default_ch ) - ch = igetch(); - else{ - if(new_ln != locmem->crs_ln) {// move fault - default_ch=0; - return FULLUPDATE; - } - ch = default_ch; - } - - new_top = 10; // default 10 - switch (ch) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if( (num = search_num(ch, last_line)) != -1 ) - new_ln = num + 1; - break; - case 'q': - case 'e': - case KEY_LEFT: - if(currmode & MODE_SELECT && locmem->crs_ln>0){ - char genbuf[PATHLEN]; - fileheader_t *fhdr = &headers[locmem->crs_ln - locmem->top_ln]; - board_select(); - setbdir(genbuf, currboard); - locmem = getkeep(genbuf, 0, 1); - locmem->crs_ln = fhdr->multi.refer.ref; - num = locmem->crs_ln - p_lines + 1; - locmem->top_ln = num < 1 ? 1 : num; - mode = NEWDIRECT; - } - else - mode = - (currmode & MODE_DIGEST) ? board_digest() : DOQUIT; - break; - case '#': - { - char aidc[100]; - aidu_t aidu = 0; - char dirfile[PATHLEN]; - char *sp; - int n = -1; - - if(!getdata(b_lines, 0, "·j´M" AID_DISPLAYNAME ": #", aidc, 20, LCECHO)) - { - move(b_lines, 0); - clrtoeol(); - mode = FULLUPDATE; - break; - } - - if((currmode & MODE_SELECT) || - (currstat == RMAIL)) - { - move(21, 0); - clrtobot(); - move(22, 0); - prints("¦¹ª¬ºA¤UµLªk¨Ï¥Î·j´M" AID_DISPLAYNAME "¥\\¯à"); - pressanykey(); - mode = FULLUPDATE; - break; - } - - /* strip leading spaces and '#' */ - sp = aidc; - while(*sp == ' ') - sp ++; - if(*sp == '#') - sp ++; - - if((aidu = aidc2aidu(sp)) > 0) - { - /* search bottom */ - /* FIXME: ¸m©³¤å¦ý¨S¦C¦b .DIR.bottom ªº¦b³o¬q·|·j¤£¨ì¡A - ¦b¤U¤@¬q search board ®É¤~·|·j¨ì¥»Åé¡CÃø¸Ñ¡C */ - { - char buf[FNLEN]; - - snprintf(buf, FNLEN, "%s.bottom", FN_DIR); - setbfile(dirfile, currboard, buf); - if((n = search_aidu(dirfile, aidu)) >= 0) - { - n += getbtotal(currbid); - /* ¤£¥i¥Î bottom_line¡A¦]¬°¦pªG¬O¦b digest mode¡A - bottom_line ·|¬O¤åºKªº¼Æ¥Ø¡A¦Ó¤£¬O¯u¥¿ªº¤å³¹¼Æ */ - if(currmode & MODE_DIGEST) - { - newdirect_new_ln = n; - - new_ln = locmem->crs_ln; - /* dirty hack for crs_ln = 1, then HOME pressed */ - - default_ch = KEY_TAB; - mode = DONOTHING; - break; - } - } - } - if(n < 0) - /* search board */ - { - setbfile(dirfile, currboard, FN_DIR); - n = search_aidu(dirfile, aidu); - if(n >= 0 && (currmode & MODE_DIGEST)) - /* switch to normal read mode */ - { - newdirect_new_ln = n; - - new_ln = locmem->crs_ln; - /* dirty hack for crs_ln = 1, then HOME pressed */ - - default_ch = KEY_TAB; - mode = DONOTHING; - break; - } - } - if(n < 0) - /* search digest */ - { - setbfile(dirfile, currboard, fn_mandex); - n = search_aidu(dirfile, aidu); - if(n >= 0 && !(currmode & MODE_DIGEST)) - /* switch to digest mode */ - { - newdirect_new_ln = n; - - new_ln = locmem->crs_ln; - /* dirty hack for crs_ln = 1, then HOME pressed */ - - default_ch = KEY_TAB; - mode = DONOTHING; - break; - } - } - } /* if(aidu > 0) */ - if(n < 0) - { - move(21, 0); - clrtobot(); - move(22, 0); - if(aidu <= 0) - prints("¤£¦Xªkªº" AID_DISPLAYNAME "¡A½Ð½T©w¿é¤J¬O¥¿½Tªº"); - else - prints("§ä¤£¨ì³oÓ" AID_DISPLAYNAME "¡A¥i¯à¬O¤å³¹¤w®ø¥¢¡A©Î¬O§A§ä¿ù¬ÝªO¤F"); - pressanykey(); - mode = FULLUPDATE; - } /* if(n < 0) */ - else - { - new_ln = n + 1; - move(b_lines, 0); - clrtoeol(); - mode = DONOTHING; - } - } - break; - case Ctrl('L'): - redrawwin(); - refresh(); - break; - - case Ctrl('H'): - mode = select_read(locmem, RS_NEWPOST); - break; - - case 'Z': - mode = select_read(locmem, RS_RECOMMEND); - break; - - case 'a': - mode = select_read(locmem, RS_AUTHOR); - break; - - case 'A': - mode = select_read(locmem, RS_MONEY); - break; - - case 'G': - mode = select_read(locmem, RS_MARK); - break; - - case '/': - case '?': - mode = select_read(locmem, RS_KEYWORD); - break; - - case 'S': - mode = select_read(locmem, RS_TITLE); - break; - - case '!': - mode = select_read(locmem, RS_KEYWORD_EXCLUDE); - break; - - case '=': - new_ln = thread(locmem, RELATE_FIRST); - break; - - case '\\': - new_ln = thread(locmem, CURSOR_FIRST); - break; - - case ']': - new_ln = thread(locmem, RELATE_NEXT); - break; - - case '+': - new_ln = thread(locmem, CURSOR_NEXT); - break; - - case '[': - new_ln = thread(locmem, RELATE_PREV); - break; - - case '-': - new_ln = thread(locmem, CURSOR_PREV); - break; - - case '<': - case ',': - new_ln = thread(locmem, NEWPOST_PREV); - break; - - case '.': - case '>': - new_ln = thread(locmem, NEWPOST_NEXT); - break; - - case 'p': - case 'k': - case KEY_UP: - if (locmem->crs_ln <= 1) { - new_ln = last_line; - new_top = p_lines-1; - } else { - new_ln = locmem->crs_ln - 1; - new_top = p_lines - 2; - } - break; - - case 'n': - case 'j': - case KEY_DOWN: - new_ln = locmem->crs_ln + 1; - new_top = 1; - break; - - case ' ': - case KEY_PGDN: - case 'N': - case Ctrl('F'): - new_ln = locmem->top_ln + p_lines; - new_top = 0; - break; - - case KEY_PGUP: - case Ctrl('B'): - case 'P': - new_ln = locmem->top_ln - p_lines; - new_top = 0; - break; - - /* add home(top entry) support? */ - case KEY_HOME: - new_ln = 0; - new_top = 0; - break; - - case KEY_END: - case '$': - new_ln = last_line; - new_top = p_lines-1; - break; - - case 'F': - case 'U': - if (HasUserPerm(PERM_FORWARD) && locmem->crs_ln>0) { - mail_forward(&headers[locmem->crs_ln - locmem->top_ln], - currdirect, ch /* == 'U' */ ); - /* by CharlieL */ - // mode = READ_REDRAW; - return FULLUPDATE; - } - break; - - case Ctrl('Q'): - if(locmem->crs_ln>0) - mode = my_query(headers[locmem->crs_ln - locmem->top_ln].owner); - break; - - case Ctrl('S'): - if (HasUserPerm(PERM_ACCOUNTS|PERM_SYSOP) && locmem->crs_ln>0) { - int id; - userec_t muser; - - strlcpy(currauthor, - headers[locmem->crs_ln - locmem->top_ln].owner, - sizeof(currauthor)); - stand_title("¨Ï¥ÎªÌ³]©w"); - move(1, 0); - if ((id = getuser(headers[locmem->crs_ln - locmem->top_ln].owner, &muser))) { - user_display(&muser, 1); - if( HasUserPerm(PERM_ACCOUNTS) ) - uinfo_query(&muser, 1, id); - else - pressanykey(); - } - mode = FULLUPDATE; - } - break; - - /* rocker.011018: ±Ä¥Î·sªºtag¼Ò¦¡ */ - case 't': - if(locmem->crs_ln == 0) - break; - /* ±N쥻¦b Read() ¸Ì±ªº "TagNum = 0" ²¾¦Ü¦¹³B */ - if ((currstat & RMAIL && TagBoard != 0) || - (!(currstat & RMAIL) && TagBoard != bid)) { - if (currstat & RMAIL) - TagBoard = 0; - else - TagBoard = bid; - TagNum = 0; - } - /* rocker.011112: ¸Ñ¨M¦Aselect mode¼Ð°O¤å³¹ªº°ÝÃD */ - if (Tagger(atoi(headers[locmem->crs_ln - locmem->top_ln].filename + 2), - (currmode & MODE_SELECT) ? - (headers[locmem->crs_ln - locmem->top_ln].multi.refer.ref) : - locmem->crs_ln, TAG_TOGGLE)) - { -// (*doentry) (locmem->crs_ln, &headers[locmem->crs_ln-locmem->top_ln]); - locmem->crs_ln ++; - // new_ln = locmem->crs_ln + 1; - // new_top = 1; - // mode = FULLUPDATE; - // mode = PART_REDRAW; - mode = PARTUPDATE; - } - break; - - case Ctrl('C'): - if (TagNum) { - TagNum = 0; - mode = FULLUPDATE; - } - break; - - case Ctrl('T'): - /* XXX duplicated code, copy from case 't' */ - if ((currstat & RMAIL && TagBoard != 0) || - (!(currstat & RMAIL) && TagBoard != bid)) { - if (currstat & RMAIL) - TagBoard = 0; - else - TagBoard = bid; - TagNum = 0; - } - mode = TagThread(currdirect); - break; - - case Ctrl('D'): - mode = TagPruner(bid); - break; - - case '\n': - case '\r': - case 'l': - case KEY_RIGHT: - ch = 'r'; - default: - if( ch == 'h' && currmode & (MODE_DIGEST) ) - break; - if (ch > 0 && ch <= onekey_size) { - int (*func)() = rcmdlist[ch - 1].func; - if(rcmdlist[ch - 1].needitem && locmem->crs_ln == 0) - break; - if (func != NULL){ - num = locmem->crs_ln - bottom_line; - - if(!rcmdlist[ch - 1].needitem) - mode = (*func)(); - else if( num > 0 ){ - sprintf(direct,"%s.bottom", currdirect); - mode= (*func)(num, &headers[locmem->crs_ln-locmem->top_ln], - direct, locmem->crs_ln - locmem->top_ln); - } - else - mode = (*func)(locmem->crs_ln, - &headers[locmem->crs_ln - locmem->top_ln], - currdirect, locmem->crs_ln - locmem->top_ln); - if(mode == READ_SKIP) - mode = lastmode; - - // ¥H¤U³o´XºØ mode n¦A³B²z´å¼Ð - if(mode == READ_PREV || mode == READ_NEXT || - mode == RELATE_PREV || mode == RELATE_FIRST || - mode == AUTHOR_NEXT || mode == AUTHOR_PREV || - mode == RELATE_NEXT){ - lastmode = mode; - - switch(mode){ - case READ_PREV: - new_ln = locmem->crs_ln - 1; - break; - case READ_NEXT: - new_ln = locmem->crs_ln + 1; - break; - case RELATE_PREV: - new_ln = thread(locmem, RELATE_PREV); - break; - case RELATE_NEXT: - new_ln = thread(locmem, RELATE_NEXT); - /* XXX: Ū¨ì³Ì«á¤@½gn¸õ¥X¨Ó */ - if( new_ln == locmem->crs_ln ){ - default_ch = 0; - return FULLUPDATE; - } - break; - case RELATE_FIRST: - new_ln = thread(locmem, RELATE_FIRST); - break; - case AUTHOR_PREV: - new_ln = thread(locmem, AUTHOR_PREV); - break; - case AUTHOR_NEXT: - new_ln = thread(locmem, AUTHOR_NEXT); - break; - } - mode = DONOTHING; default_ch = 'r'; - } - else { - default_ch = 0; - lastmode = DONOTHING; - } - } //end if (func != NULL) - } // ch > 0 && ch <= onekey_size - break; - } // end switch - } while (mode == DONOTHING); - return mode; -} - -// recbase: Åã¥Ü¦ì¸mªº¶}ÀY -// headers_size:nÅã¥Ü´X¦æ -// last_line: ¥þªO .DIR + ¸m©³ ªº¦³®Ä¼Æ¥Ø -// bottom_line: ¥þªO .DIR (µL¸m©³) ªº¦³®Ä¼Æ¥Ø - -// XXX never return -1! - -static int -get_records_and_bottom(char *direct, fileheader_t* headers, - int recbase, int headers_size, int last_line, int bottom_line) -{ - // n: ¸m©³°£¥~ªº¥iÅã¥Ü¼Æ¥Ø - int n = bottom_line - recbase + 1, rv = 0; - - if( last_line < 1) // §¹¥þ¨SªF¦è - return 0; - - // ¤£Åã¥Ü¸m©³ªº±¡§Î - if( n >= headers_size || (currmode & (MODE_SELECT | MODE_DIGEST)) ) - { - rv = get_records(direct, headers, sizeof(fileheader_t), - recbase, headers_size); - return rv > 0 ? rv : 0; - } - - //////// Åã¥Ü¥»¤å+¸m©³: //////// - - // Ū¨ú .DIR ¥»¤å - if (n > 0) - { - n = get_records(direct, headers, sizeof(fileheader_t), recbase, n); - if (n < 0) n = 0; - rv += n; // rv ¬°¦³®Ä¥»¤å¼Æ - - recbase = 1; - } else { - // n <= 0 - recbase = 1 + (-n); - } - - // Ū¨ú¸m©³ (ª`·N recbase ¥i¯à¶W¹L bottom_line, ¤]´N¬O¥H¸m©³²Ä n Ó¶}©l) - n = last_line - bottom_line +1 - (recbase-1); - if (rv + n > headers_size) - n = headers_size - rv; - - if (n > 0) { - char directbottom[PATHLEN]; - snprintf(directbottom, sizeof(directbottom), "%s.bottom", direct); - n = get_records(directbottom, headers+rv, sizeof(fileheader_t), recbase, n); - if (n < 0) n = 0; - rv += n; - } - - return rv; -} - -void -i_read(int cmdmode, const char *direct, void (*dotitle) (), - void (*doentry) (), const onekey_t * rcmdlist, int bidcache) -{ - keeploc_t *locmem = NULL; - int recbase = 0, mode; - int entries = 0; - char currdirect0[PATHLEN]; - int last_line0 = last_line; - int bottom_line = 0; - fileheader_t *headers0 = headers; - int headers_size0 = headers_size; - - strlcpy(currdirect0, currdirect, sizeof(currdirect0)); -#define FHSZ sizeof(fileheader_t) - /* Ptt: ³oÃä headers ¥i¥H°w¹ï¬ÝªOªº³Ì«á 60 ½g°µ cache */ - headers_size = p_lines; - headers = (fileheader_t *) calloc(headers_size, FHSZ); - assert(headers != NULL); - strlcpy(currdirect, direct, sizeof(currdirect)); - mode = NEWDIRECT; - - do { - /* ¨Ì¾Ú mode Åã¥Ü fileheader */ - setutmpmode(cmdmode); - switch (mode) { - case DONOTHING: - break; - - case NEWDIRECT: /* ²Ä¤@¦¸¸ü¤J¦¹¥Ø¿ý */ - case DIRCHANGED: - if (bidcache > 0 && !(currmode & (MODE_SELECT | MODE_DIGEST))){ - if( (last_line = getbtotal(currbid)) == 0 ){ - setbtotal(currbid); - setbottomtotal(currbid); - last_line = getbtotal(currbid); - } - bottom_line = last_line; - last_line += getbottomtotal(currbid); - } - else - bottom_line = last_line = get_num_records(currdirect, FHSZ); - - if (mode == NEWDIRECT) { - int num; - num = last_line - p_lines + 1; - locmem = getkeep(currdirect, num < 1 ? 1 : num, - bottom_line ? bottom_line : last_line); - if(newdirect_new_ln >= 0) - { - locmem->crs_ln = newdirect_new_ln + 1; - newdirect_new_ln = -1; - } - } - recbase = -1; - /* no break */ - - default: // for any unknown keys - case FULLUPDATE: - (*dotitle) (); - /* no break */ - - case PARTUPDATE: - if (headers_size != p_lines) { - headers_size = p_lines; - headers = (fileheader_t *) realloc(headers, headers_size*FHSZ); - assert(headers); - } - - /* In general, records won't be reloaded in PARTUPDATE state. - * But since a board is often changed and cached, it is always - * reloaded here. */ - if (bidcache > 0 && !(currmode & (MODE_SELECT | MODE_DIGEST))) { - int rec_num; - bottom_line = getbtotal(currbid); - rec_num = bottom_line + getbottomtotal(currbid); - if (last_line != rec_num) { - last_line = rec_num; - recbase = -1; - } - } - - if (recbase != locmem->top_ln) { //headers reload - recbase = locmem->top_ln; - if (recbase > last_line) { - recbase = last_line - headers_size + 1; - if (recbase < 1) - recbase = 1; - locmem->top_ln = recbase; - } - /* XXX if entries return -1 or black-hole */ - entries = get_records_and_bottom(currdirect, - headers, recbase, headers_size, last_line, bottom_line); - } - if (locmem->crs_ln > last_line) - locmem->crs_ln = last_line; - move(3, 0); - clrtobot(); - /* no break */ - case PART_REDRAW: - move(3, 0); - if( last_line == 0 ) - outs(" ¨S¦³¤å³¹..."); - else { - int i; - for( i = 0; i < entries ; i++ ) - (*doentry) (locmem->top_ln + i, &headers[i]); - } - /* no break */ - case READ_REDRAW: - if(curredit & EDIT_ITEM) - outmsglr(ANSI_COLOR(44) " ¨p¤H¦¬Âà " ANSI_COLOR(30;47), 10, - " Ä~Äò? ", 7); - else if (curredit & EDIT_MAIL) - outmsglr(MSG_MAILER, MSG_MAILER_LEN, "", 0); - else - outmsglr(MSG_POSTER, MSG_POSTER_LEN, "", 0); - break; - - case TITLE_REDRAW: - (*dotitle) (); - break; - - case HEADERS_RELOAD: - if (recbase != locmem->top_ln) { - recbase = locmem->top_ln; - if (recbase > last_line) { - recbase = last_line - p_lines + 1; - if (recbase < 1) - recbase = 1; - locmem->top_ln = recbase; - } - if(headers_size != p_lines) { - headers_size = p_lines; - headers = (fileheader_t *) realloc(headers, headers_size*FHSZ); - assert(headers); - } - /* XXX if entries return -1 */ - entries = - get_records_and_bottom(currdirect, headers, recbase, - headers_size, last_line, bottom_line); - } - break; - } //end switch - mode = i_read_key(rcmdlist, locmem, currbid, bottom_line); - } while (mode != DOQUIT); -#undef FHSZ - - free(headers); - last_line = last_line0; - headers = headers0; - headers_size = headers_size0; - strlcpy(currdirect, currdirect0, sizeof(currdirect)); - return; -} diff --git a/mbbsd/record.c b/mbbsd/record.c deleted file mode 100644 index d50df1d9..00000000 --- a/mbbsd/record.c +++ /dev/null @@ -1,666 +0,0 @@ -/* $Id$ */ - -#include "bbs.h" - -#undef HAVE_MMAP -#define BUFSIZE 512 - -#define safewrite write - -int -get_num_records(const char *fpath, int size) -{ - struct stat st; - if (stat(fpath, &st) == -1) - { - /* TODO: delete this entry, or mark as read */ - return 0; - } - return st.st_size / size; -} - -int -get_sum_records(const char *fpath, int size) -{ - struct stat st; - int ans = 0; - FILE *fp; - fileheader_t fhdr; - char buf[200], *p; - - // Ptt : should avoid big loop - if ((fp = fopen(fpath, "r"))==NULL) - return -1; - - strlcpy(buf, fpath, sizeof(buf)); - p = strrchr(buf, '/'); - assert(p); - p++; - - while (fread(&fhdr, size, 1, fp)==1) { - strlcpy(p, fhdr.filename, sizeof(buf) - (p - buf)); - if (stat(buf, &st) == 0 && S_ISREG(st.st_mode) && st.st_nlink == 1) - ans += st.st_size; - } - fclose(fp); - return ans / 1024; -} - -int -get_record_keep(const char *fpath, void *rptr, int size, int id, int *fd) -{ - /* ©M get_record() ¤@¼Ë. ¤£¹LÂÇ¥Ñ *fd, ¥i¨Ï¦P¤@ÓÀɮפ£n¤@ª½«½Æ¶}Ãö */ - if (id >= 1 && - (*fd > 0 || - ((*fd = open(fpath, O_RDONLY, 0)) > 0))){ // FIXME leak if *fd==0 - if (lseek(*fd, (off_t) (size * (id - 1)), SEEK_SET) != -1) { - if (read(*fd, rptr, size) == size) { - return 0; - } - } - } - return -1; -} - -int -get_record(const char *fpath, void *rptr, int size, int id) -{ - int fd = -1; - /* TODO merge with get_records() */ - - if (id >= 1 && (fd = open(fpath, O_RDONLY, 0)) != -1) { - if (lseek(fd, (off_t) (size * (id - 1)), SEEK_SET) != -1) { - if (read(fd, rptr, size) == size) { - close(fd); - return 0; - } - } - close(fd); - } - return -1; -} - -int -get_records(const char *fpath, void *rptr, int size, int id, int number) -{ - int fd; - - if (id < 1 || (fd = open(fpath, O_RDONLY, 0)) == -1) - return -1; - - if (lseek(fd, (off_t) (size * (id - 1)), SEEK_SET) == -1) { - close(fd); - return 0; - } - if ((id = read(fd, rptr, size * number)) == -1) { - close(fd); - return -1; - } - close(fd); - return id / size; -} - -int -substitute_record(const char *fpath, const void *rptr, int size, int id) -{ - int fd; - int offset=size * (id - 1); - if (id < 1 || (fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) - return -1; - - lseek(fd, (off_t) (offset), SEEK_SET); - PttLock(fd, offset, size, F_WRLCK); - write(fd, rptr, size); - PttLock(fd, offset, size, F_UNLCK); - close(fd); - - return 0; -} - -/* return index>0 if thisstamp==stamp[index], - * return -index<0 if stamp[index-1]<thisstamp<stamp[index+1], XXX thisstamp ?<>? stamp[index] - * or XXX filename[index]="" - * return 0 if error - */ -int -getindex_m(const char *direct, fileheader_t *fhdr, int end, int isloadmoney) -{ // Ptt: ±q«e±§ä«Ü¶O¤O ¤Ó¼É¤O - int fd = -1, begin = 1, i, s, times, stamp; - fileheader_t fh; - - int n = get_num_records(direct, sizeof(fileheader_t)); - if( end > n || end<=0 ) - end = n; - stamp = atoi(fhdr->filename + 2); - for( i = (begin + end ) / 2, times = 0 ; - end >= begin && times < 20 ; /* ³Ì¦h¥u§ä 20 ¦¸ */ - i = (begin + end ) / 2, ++times ){ - if( get_record_keep(direct, &fh, sizeof(fileheader_t), i, &fd)==-1 || - !fh.filename[0] ) - break; - s = atoi(fh.filename + 2); - if( s > stamp ) - end = i - 1; - else if( s == stamp ){ - close(fd); - if(isloadmoney) - fhdr->multi.money = fh.multi.money; - return i; - } - else - begin = i + 1; - } - - if( times < 20) // Not forever loop. It any because of deletion. - { - close(fd); - return -i; - } - if( fd != -1 ) - close(fd); - return 0; -} - -inline int -getindex(const char *direct, fileheader_t *fhdr, int end) -{ - return getindex_m(direct, fhdr, end, 0); -} - -int -substitute_ref_record(const char *direct, fileheader_t * fhdr, int ent) -{ - fileheader_t hdr; - char fname[PATHLEN]; - int num = 0; - - /* rocker.011018: ¦ê±µ¼Ò¦¡¥Îreference¼W¶i®Ä²v */ - if (!(fhdr->filemode & FILE_BOTTOM) && (fhdr->multi.refer.flag) && - (num = fhdr->multi.refer.ref)){ - setdirpath(fname, direct, FN_DIR); - get_record(fname, &hdr, sizeof(hdr), num); - if (strcmp(hdr.filename, fhdr->filename)) { - if((num = getindex_m(fname, fhdr, num, 1))>0) { - substitute_record(fname, fhdr, sizeof(*fhdr), num); - } - } - else if(num>0) { - fhdr->multi.money = hdr.multi.money; - substitute_record(fname, fhdr, sizeof(*fhdr), num); - } - fhdr->multi.refer.flag = 1; - fhdr->multi.refer.ref = num; // Ptt: update now! - } - substitute_record(direct, fhdr, sizeof(*fhdr), ent); - return num; -} - - -/* rocker.011022: ÁקKlockÀɶ}±Ò®É¤£¥¿±`Â_½u,³y¦¨¥Ã¤[lock */ -#ifndef _BBS_UTIL_C_ -static int -force_open(const char *fname) -{ - int fd; - time4_t expire; - - expire = now - 3600; /* lock ¦s¦b¶W¹L¤@Ó¤p®É´N¬O¦³°ÝÃD! */ - - if (dasht(fname) < expire) - return -1; - unlink(fname); - fd = open(fname, O_WRONLY | O_TRUNC, 0644); - - return fd; -} -#endif - -/* new/old/lock file processing */ -typedef struct nol_t { - char newfn[256]; - char oldfn[256]; - char lockfn[256]; -} nol_t; - -#ifndef _BBS_UTIL_C_ -static void -nolfilename(nol_t * n, const char *fpath) -{ - snprintf(n->newfn, sizeof(n->newfn), "%s.new", fpath); - snprintf(n->oldfn, sizeof(n->oldfn), "%s.old", fpath); - snprintf(n->lockfn, sizeof(n->lockfn), "%s.lock", fpath); -} -#endif - -int -delete_records(const char *fpath, int size, int id, int num) -{ - char abuf[BUFSIZE]; - int fi, fo, locksize=0, readsize=0, offset = size * (id - 1), c, d=0; - struct stat st; - - - if ((fi=open(fpath, O_RDONLY, 0)) == -1) - return -1; - - if ((fo=open(fpath, O_WRONLY, 0)) == -1) - { - close(fi); - return -1; - } - - if(fstat(fi, &st)==-1) - { close(fo); close(fi); return -1;} - - locksize = st.st_size - offset; - readsize = locksize - size*num; - if (locksize < 0 ) - { close(fo); close(fi); return -1;} - - PttLock(fo, offset, locksize, F_WRLCK); - if(readsize>0) - { - lseek(fi, offset+size, SEEK_SET); - lseek(fo, offset, SEEK_SET); - while( d<readsize && (c = read(fi, abuf, BUFSIZE))>0) - { - write(fo, abuf, c); - d=d+c; - } - } - close(fi); - ftruncate(fo, st.st_size - size*num); - PttLock(fo, offset, locksize, F_UNLCK); - close(fo); - return 0; - -} - - -int delete_record(const char *fpath, int size, int id) -{ - return delete_records(fpath, size, id, 1); -} - - -#ifndef _BBS_UTIL_C_ -#ifdef SAFE_ARTICLE_DELETE -void safe_delete_range(const char *fpath, int id1, int id2) -{ - int fd, i; - fileheader_t fhdr; - char fullpath[STRLEN], *t; - strlcpy(fullpath, fpath, sizeof(fullpath)); - t = strrchr(fullpath, '/'); - assert(t); - t++; - if( (fd = open(fpath, O_RDONLY)) == -1 ) - return; - for( i = 1 ; (read(fd, &fhdr, sizeof(fileheader_t)) == - sizeof(fileheader_t)) ; ++i ){ - strcpy(t, fhdr.filename); - /* rocker.011018: add new tag delete */ - if (!((fhdr.filemode & FILE_MARKED) || /* ¼Ð°O */ - (fhdr.filemode & FILE_DIGEST) || /* ¤åºK */ - (id1 && (i < id1 || i > id2)) || /* range */ - (!id1 && Tagger(atoi(t + 2), i, TAG_NIN)))) /* TagList */ - safe_article_delete(i, &fhdr, fpath); - } - close(fd); -} -#endif - -int -delete_range(const char *fpath, int id1, int id2) -{ - fileheader_t fhdr; - nol_t my; - char fullpath[STRLEN], *t; - int fdr, fdw, fd; - int count, dcount=0; - - nolfilename(&my, fpath); - - if ((fd = open(my.lockfn, O_RDWR | O_CREAT | O_APPEND, 0644)) == -1) - return -1; - - flock(fd, LOCK_EX); - - if ((fdr = open(fpath, O_RDONLY, 0)) == -1) { - flock(fd, LOCK_UN); - close(fd); - return -1; - } - if ( - ((fdw = open(my.newfn, O_WRONLY | O_CREAT | O_EXCL, 0644)) == -1) && - ((fdw = force_open(my.newfn)) == -1)) { - close(fdr); - flock(fd, LOCK_UN); - close(fd); - return -1; - } - count = 1; - strlcpy(fullpath, fpath, sizeof(fullpath)); - t = strrchr(fullpath, '/'); - assert(t); - t++; - - while (read(fdr, &fhdr, sizeof(fileheader_t)) == sizeof(fileheader_t)) { - strcpy(t, fhdr.filename); - - /* rocker.011018: add new tag delete */ - if ( - (fhdr.filemode & FILE_MARKED) || /* ¼Ð°O */ - ((fhdr.filemode & FILE_DIGEST) && (currstat != RMAIL) )|| - /* ¤åºK , FILE_DIGEST is used as REPLIED in mail menu.*/ - (id1 && (count < id1 || count > id2)) || /* range */ - (!id1 && Tagger(atoi(t + 2), count, TAG_NIN))) { /* TagList */ - if ((safewrite(fdw, &fhdr, sizeof(fileheader_t)) == -1)) { - close(fdr); - close(fdw); - unlink(my.newfn); - flock(fd, LOCK_UN); - close(fd); - return -1; - } - } else { - //if (dashd(fullpath)) - unlink(fullpath); - dcount++; - } - ++count; - } - close(fdr); - close(fdw); - if (Rename(fpath, my.oldfn) == -1 || Rename(my.newfn, fpath) == -1) { - flock(fd, LOCK_UN); - close(fd); - return -1; - } - flock(fd, LOCK_UN); - close(fd); - return dcount; -} -#endif - - -#ifdef SAFE_ARTICLE_DELETE -int -safe_article_delete(int ent, const fileheader_t *fhdr, const char *direct) -{ - fileheader_t newfhdr; - memcpy(&newfhdr, fhdr, sizeof(fileheader_t)); - sprintf(newfhdr.title, "(¥»¤å¤w³Q§R°£)"); - strcpy(newfhdr.filename, ".deleted"); - strcpy(newfhdr.owner, "-"); - substitute_record(direct, &newfhdr, sizeof(newfhdr), ent); - return 0; -} - -int -safe_article_delete_range(const char *direct, int from, int to) -{ - fileheader_t newfhdr; - int fd; - char fn[128], *ptr; - - strlcpy(fn, direct, sizeof(fn)); - if( (ptr = rindex(fn, '/')) == NULL ) - return 0; - - ++ptr; - if( (fd = open(direct, O_RDWR)) != -1 && - lseek(fd, sizeof(fileheader_t) * (from - 1), SEEK_SET) != -1 ){ - - for( ; from <= to ; ++from ){ - read(fd, &newfhdr, sizeof(fileheader_t)); - if( newfhdr.filemode & (FILE_MARKED | FILE_DIGEST) ) - continue; - if(newfhdr.filename[0]=='L') newfhdr.filename[0]='M'; - strlcpy(ptr, newfhdr.filename, sizeof(newfhdr.filename)); - unlink(fn); - - sprintf(newfhdr.title, "(¥»¤å¤w³Q§R°£)"); - strcpy(newfhdr.filename, ".deleted"); - strcpy(newfhdr.owner, "-"); - // because off_t is unsigned, we could NOT seek backward. - lseek(fd, sizeof(fileheader_t) * (from - 1), SEEK_SET); - write(fd, &newfhdr, sizeof(fileheader_t)); - } - close(fd); - } - return 0; -} - - -#endif - -int -apply_record(const char *fpath, int (*fptr) (void *item, void *optarg), int size, void *arg){ - char abuf[BUFSIZE]; - int fp; - - if((fp=open(fpath, O_RDONLY, 0)) == -1) - return -1; - - assert(size<=sizeof(abuf)); - while (read(fp, abuf, size) == (size_t)size) - if ((*fptr) (abuf, arg) == QUIT) { - close(fp); - return QUIT; - } - close(fp); - return 0; -} - -/* mail / post ®É¡A¨Ì¾Ú®É¶¡«Ø¥ßÀɮסA¥[¤W¶lÂW */ -int -stampfile_u(char *fpath, fileheader_t * fh) - // Ptt: stampfile_u: won't clear fileheader - // stampfile: will clear fileheader -{ - register char *ip = fpath; - time4_t dtime = COMMON_TIME; - struct tm *ptime; -#ifdef _BBS_UTIL_C_ - int fp = 0; //Ptt: don't need to check - // for utils, the time may be the same between several runs, by scw -#endif - - if (access(fpath, X_OK | R_OK | W_OK)) - mkdir(fpath, 0755); - - while (*(++ip)); - *ip++ = '/'; -#ifdef _BBS_UTIL_C_ - do { -#endif - sprintf(ip, "M.%d.A.%3.3X", (int)(++dtime), (unsigned int)(random() & 0xFFF)); -#ifdef _BBS_UTIL_C_ - if (fp == -1 && errno != EEXIST) - return -1; - } while ((fp = open(fpath, O_CREAT | O_EXCL | O_WRONLY, 0644)) == -1); - close(fp); -#endif - strlcpy(fh->filename, ip, sizeof(fh->filename)); - ptime = localtime4(&dtime); - snprintf(fh->date, sizeof(fh->date), - "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); - return 0; -} - -inline int -stampfile(char *fpath, fileheader_t * fh) -{ - memset(fh, 0, sizeof(fileheader_t)); - return stampfile_u(fpath, fh); -} - -void -stampdir(char *fpath, fileheader_t * fh) -{ - register char *ip = fpath; - time4_t dtime = COMMON_TIME; - struct tm *ptime; - - if (access(fpath, X_OK | R_OK | W_OK)) - mkdir(fpath, 0755); - - while (*(++ip)); - *ip++ = '/'; - do { - sprintf(ip, "D%X", (int)++dtime & 07777); - } while (mkdir(fpath, 0755) == -1); - memset(fh, 0, sizeof(fileheader_t)); - strlcpy(fh->filename, ip, sizeof(fh->filename)); - ptime = localtime4(&dtime); - snprintf(fh->date, sizeof(fh->date), - "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); -} - -void -stamplink(char *fpath, fileheader_t * fh) -{ - register char *ip = fpath; - time4_t dtime = COMMON_TIME; - struct tm *ptime; - - if (access(fpath, X_OK | R_OK | W_OK)) - mkdir(fpath, 0755); - - while (*(++ip)); - *ip++ = '/'; - do { - sprintf(ip, "S%X", (int)++dtime); - } while (symlink("temp", fpath) == -1); - memset(fh, 0, sizeof(fileheader_t)); - strlcpy(fh->filename, ip, sizeof(fh->filename)); - ptime = localtime4(&dtime); - snprintf(fh->date, sizeof(fh->date), - "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); -} - -int -append_record(const char *fpath, const fileheader_t * record, int size) -{ - int fd, fsize=0, index; - struct stat st; - - if ((fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) { - char buf[STRLEN]; - assert(errno != EISDIR); - sprintf(buf, "id(%s), open(%s)", cuser.userid, fpath); - perror(buf); - return -1; - } - flock(fd, LOCK_EX); - - if(fstat(fd, &st)!=-1) - fsize = st.st_size; - - index = fsize / size; - lseek(fd, index * size, SEEK_SET); // avoid offset - - safewrite(fd, record, size); - - flock(fd, LOCK_UN); - close(fd); - return index + 1; -} - -int -append_record_forward(char *fpath, fileheader_t * record, int size, const char *origid) -{ -#if !defined(_BBS_UTIL_C_) - if (get_num_records(fpath, sizeof(fileheader_t)) <= MAX_KEEPMAIL * 2) { - FILE *fp; - char buf[512]; - int n; - - for (n = strlen(fpath) - 1; fpath[n] != '/' && n > 0; n--); - if (n + sizeof(".forward") > sizeof(buf)) - return -1; - memcpy(buf, fpath, n+1); - strcpy(buf + n + 1, ".forward"); - if ((fp = fopen(buf, "r"))) { - - char address[64]; - int flIdiotSent2Self = 0; - int oidlen = origid ? strlen(origid) : 0; - - address[0] = 0; - fscanf(fp, "%63s", address); - fclose(fp); - /* some idiots just set forwarding to themselves. - * and even after we checked "sameid", some still - * set STUPID_ID.bbs@host <- "¦Û¥H¬°Áo©ú" - * damn it, we have a complex rule now. - */ - if(oidlen > 0) { - if (strncasecmp(address, origid, oidlen) == 0) - { - int addrlen = strlen(address); - if( addrlen == oidlen || - (addrlen > oidlen && - strcasecmp(address + oidlen, str_mail_address) == 0)) - flIdiotSent2Self = 1; - } - } - - if (buf[0] && buf[0] != ' ' && !flIdiotSent2Self) { - buf[n + 1] = 0; - strcat(buf, record->filename); - append_record(fpath, record, size); -#ifndef USE_BSMTP - bbs_sendmail(buf, record->title, address); -#else - bsmtp(buf, record->title, address); -#endif - return 0; - } - } - } -#endif - - append_record(fpath, record, size); - - return 0; -} - -#ifndef _BBS_UTIL_C_ -void -setaidfile(char *buf, const char *bn, aidu_t aidu) -{ - // try to load by AID - int bid = 0; - int n = 0, fd = 0; - char bfpath[PATHLEN] = ""; - boardheader_t *bh = NULL; - fileheader_t fh; - - buf[0] = 0; - bid = getbnum(bn); - - if (bid <= 0) return; - assert(0<=bid-1 && bid-1<MAX_BOARD); - bh = getbcache(bid); - if (!HasBoardPerm(bh)) return; - - setbfile(bfpath, bh->brdname, FN_DIR); - n = search_aidu(bfpath, aidu); - - if (n < 0) return; - fd = open(bfpath, O_RDONLY); - if (fd < 0) return; - - lseek(fd, n*sizeof(fileheader_t), SEEK_SET); - memset(&fh, 0, sizeof(fh)); - if (read(fd, &fh, sizeof(fh)) > 0) - { - setbfile(buf, bh->brdname, fh.filename); - if (!dashf(buf)) - buf[0] = 0; - } - close(fd); -} -#endif diff --git a/mbbsd/register.c b/mbbsd/register.c deleted file mode 100644 index e0db7d37..00000000 --- a/mbbsd/register.c +++ /dev/null @@ -1,3040 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#define FN_REGISTER_LOG "register.log" // global registration history -#define FN_JUSTIFY "justify" -#define FN_JUSTIFY_WAIT "justify.wait" -#define FN_REJECT_NOTIFY "justify.reject" - -// New style (Regform2) file names: -#define FN_REGFORM "regform" // registration form in user home -#define FN_REGFORM_LOG "regform.log" // regform history in user home -#define FN_REQLIST "reg.wait" // request list file, in global directory (replacing fn_register) - -//////////////////////////////////////////////////////////////////////////// -// Password Hash -//////////////////////////////////////////////////////////////////////////// - -// prototype of crypt() -char *crypt(const char *key, const char *salt); - -char * -genpasswd(char *pw) -{ - if (pw[0]) { - char saltc[2], c; - int i; - - i = 9 * getpid(); - saltc[0] = i & 077; - saltc[1] = (i >> 6) & 077; - - for (i = 0; i < 2; i++) { - c = saltc[i] + '.'; - if (c > '9') - c += 7; - if (c > 'Z') - c += 6; - saltc[i] = c; - } - return crypt(pw, saltc); - } - return ""; -} - -// NOTE it will clean string in "plain" -int -checkpasswd(const char *passwd, char *plain) -{ - int ok; - char *pw; - - ok = 0; - pw = crypt(plain, passwd); - if(pw && strcmp(pw, passwd)==0) - ok = 1; - memset(plain, 0, strlen(plain)); - - return ok; -} - -//////////////////////////////////////////////////////////////////////////// -// Value Validation -//////////////////////////////////////////////////////////////////////////// -static int -HaveRejectStr(const char *s, const char **rej) -{ - int i; - char *ptr, *rejectstr[] = - {"·F", "ªü", "¤£", "§A¶ý", "¬Y", "²Â", "§b", "..", "xx", - "§AºÞ", "ºÞ§Ú", "²q", "¤Ñ¤~", "¶W¤H", - "£t", "£u", "£v", "£w", "£x", "£y", "£z", "£{", "£|", "£}", "£~", - "£¡", "£¢", "££", "£¤",/*"£¥",*/ "£¦", "£§", "£¨", "£©", "£ª", - "£¸", "£¹", "£º", "£«", "£¬", "£", "£®", "£¯", "£°", "£±", "£²", - "£³", "£´", "£µ", "£¶", "£·", NULL}; - - if( rej != NULL ) - for( i = 0 ; rej[i] != NULL ; ++i ) - if( strstr(s, rej[i]) ) - return 1; - - for( i = 0 ; rejectstr[i] != NULL ; ++i ) - if( strstr(s, rejectstr[i]) ) - return 1; - - if( (ptr = strstr(s, "£¥")) != NULL ){ - if( ptr != s && strncmp(ptr - 1, "³£¥«", 4) == 0 ) - return 0; - return 1; - } - return 0; -} - -static int -removespace(char *s) -{ - int i, index; - - for (i = 0, index = 0; s[i]; i++) { - if (s[i] != ' ') - s[index++] = s[i]; - } - s[index] = '\0'; - return index; -} - -int -bad_user_id(const char *userid) -{ - if(!is_validuserid(userid)) - return 1; - - if (strcasecmp(userid, str_new) == 0) - return 1; - -#ifdef NO_GUEST_ACCOUNT_REG - if (strcasecmp(userid, STR_GUEST) == 0) - return 1; -#endif - - /* in2: 쥻¬O¥Îstrcasestr, - ¤£¹L¦³¨Ç¤H¤¤¶¡èè¦n¥X²{³oÓ¦rÀ³¸ÓÁÙºâ¦X²z§a? */ - if( strncasecmp(userid, "fuck", 4) == 0 || - strncasecmp(userid, "shit", 4) == 0 ) - return 1; - - /* - * while((ch = *(++userid))) if(not_alnum(ch)) return 1; - */ - return 0; -} - -static char * -isvalidname(char *rname) -{ -#ifdef FOREIGN_REG - return NULL; -#else - const char *rejectstr[] = - {"ªÎ", "D", "½ÞÀY", "¤p¥Õ", "¤p©ú", "¸ô¤H", "¦Ñ¤ý", "¦Ñ§õ", "Ä_¨©", - "¥ý¥Í", "«Óô", "¦ÑÀY", "¤p©n", "¤p©j", "¬ü¤k", "¤p©f", "¤jÀY", - "¤½¥D", "¦P¾Ç", "Ä_Ä_", "¤½¤l", "¤jÀY", "¤p¤p", "¤p§Ì", "¤p©f", - "©f©f", "¼K", "¶â", "·Ý·Ý", "¤jô", "µL", - NULL}; - if( removespace(rname) && rname[0] < 0 && - strlen(rname) >= 4 && - !HaveRejectStr(rname, rejectstr) && - strncmp(rname, "¤p", 2) != 0 && //°_ÀY¬O¡u¤p¡v - strncmp(rname, "§Ú¬O", 4) != 0 && //°_ÀY¬O¡u§Ú¬O¡v - !(strlen(rname) == 4 && strncmp(&rname[2], "¨à", 2) == 0) && - !(strlen(rname) >= 4 && strncmp(&rname[0], &rname[2], 2) == 0)) - return NULL; - return "±zªº¿é¤J¤£¥¿½T"; -#endif - -} - -static char * -isvalidcareer(char *career) -{ -#ifndef FOREIGN_REG - const char *rejectstr[] = {NULL}; - if (!(removespace(career) && career[0] < 0 && strlen(career) >= 6) || - strcmp(career, "®a¸Ì") == 0 || HaveRejectStr(career, rejectstr) ) - return "±zªº¿é¤J¤£¥¿½T"; - if (strcmp(&career[strlen(career) - 2], "¤j") == 0 || - strcmp(&career[strlen(career) - 4], "¤j¾Ç") == 0 || - strcmp(career, "¾Ç¥Í¤j¾Ç") == 0) - return "³Â·Ð½Ð¥[¾Ç®Õ¨t©Ò"; - if (strcmp(career, "¾Ç¥Í°ª¤¤") == 0) - return "³Â·Ð¿é¤J¾Ç®Õ¦WºÙ"; -#else - if( strlen(career) < 6 ) - return "±zªº¿é¤J¤£¥¿½T"; -#endif - return NULL; -} - -static char * -isvalidaddr(char *addr) -{ - const char *rejectstr[] = - {"¦a²y", "»Èªe", "¤õ¬P", NULL}; - - // addr[0] > 0: check if address is starting by Chinese. - if (!removespace(addr) || strlen(addr) < 15) - return "³oÓ¦a§}¦ü¥G¨Ã¤£§¹¾ã"; - if (strstr(addr, "«H½c") != NULL || strstr(addr, "¶l¬F") != NULL) - return "©êºp§Ṳ́£±µ¨ü¶l¬F«H½c"; - if ((strstr(addr, "¥«") == NULL && strstr(addr, "É]") == NULL && - strstr(addr, "¿¤") == NULL && strstr(addr, "«Ç") == NULL) || - HaveRejectStr(addr, rejectstr) || - strcmp(&addr[strlen(addr) - 2], "¬q") == 0 || - strcmp(&addr[strlen(addr) - 2], "¸ô") == 0 || - strcmp(&addr[strlen(addr) - 2], "«Ñ") == 0 || - strcmp(&addr[strlen(addr) - 2], "§Ë") == 0 || - strcmp(&addr[strlen(addr) - 2], "°Ï") == 0 || - strcmp(&addr[strlen(addr) - 2], "¥«") == 0 || - strcmp(&addr[strlen(addr) - 2], "µó") == 0 ) - return "³oÓ¦a§}¦ü¥G¨Ã¤£§¹¾ã"; - return NULL; -} - -static char * -isvalidphone(char *phone) -{ - int i; - for( i = 0 ; phone[i] != 0 ; ++i ) - if( !isdigit((int)phone[i]) ) - return "½Ð¤£n¥[¤À¹j²Å¸¹"; - if (!removespace(phone) || - strlen(phone) < 9 || - strstr(phone, "00000000") != NULL || - strstr(phone, "22222222") != NULL ) { - return "³oÓ¹q¸Ü¸¹½X¨Ã¤£¥¿½T(½Ð§t°Ï½X)" ; - } - return NULL; -} - - -//////////////////////////////////////////////////////////////////////////// -// Account Expiring -//////////////////////////////////////////////////////////////////////////// - -/* -------------------------------- */ -/* New policy for allocate new user */ -/* (a) is the worst user currently */ -/* (b) is the object to be compared */ -/* -------------------------------- */ -static int -compute_user_value(const userec_t * urec, time4_t clock) -{ - int value; - - /* if (urec) has XEMPT permission, don't kick it */ - if ((urec->userid[0] == '\0') || (urec->userlevel & PERM_XEMPT) - /* || (urec->userlevel & PERM_LOGINOK) */ - || !strcmp(STR_GUEST, urec->userid)) - return 999999; - value = (clock - urec->lastlogin) / 60; /* minutes */ - - /* new user should register in 30 mins */ - // XXX ¥Ø«e new acccount ¨Ã¤£·|¦b utmp ¸Ì©ñ str_new... - if (strcmp(urec->userid, str_new) == 0) - return 30 - value; - -#if 0 - if (!urec->numlogins) /* ¥¼ login ¦¨¥\ªÌ¡A¤£«O¯d */ - return -1; - if (urec->numlogins <= 3) /* #login ¤Ö©ó¤TªÌ¡A«O¯d 20 ¤Ñ */ - return 20 * 24 * 60 - value; -#endif - /* ¥¼§¹¦¨µù¥UªÌ¡A«O¯d 15 ¤Ñ */ - /* ¤@¯ë±¡ªp¡A«O¯d 120 ¤Ñ */ - return (urec->userlevel & PERM_LOGINOK ? 120 : 15) * 24 * 60 - value; -} - -int -check_and_expire_account(int uid, const userec_t * urec, int expireRange) -{ - char genbuf[200]; - int val; - if ((val = compute_user_value(urec, now)) < 0) { - snprintf(genbuf, sizeof(genbuf), "#%d %-12s %15.15s %d %d %d", - uid, urec->userid, ctime4(&(urec->lastlogin)) + 4, - urec->numlogins, urec->numposts, val); - - // Y¶W¹L expireRange «h¬å¤H¡A - // ¤£µM´N return 0 - if (-val > expireRange) - { - log_usies("DATED", genbuf); - // log_usies("CLEAN", genbuf); - kill_user(uid, urec->userid); - } else val = 0; - } - return val; -} - -//////////////////////////////////////////////////////////////////////////// -// Regcode Support -//////////////////////////////////////////////////////////////////////////// - -#define REGCODE_INITIAL "v6" // always 2 characters - -static char * -getregfile(char *buf) -{ - // not in user's home because s/he could zip his/her home - snprintf(buf, PATHLEN, "jobspool/.regcode.%s", cuser.userid); - return buf; -} - -static char * -makeregcode(char *buf) -{ - char fpath[PATHLEN]; - int fd, i; - // prevent ambigious characters: oOlI - const char *alphabet = "qwertyuipasdfghjkzxcvbnmoQWERTYUPASDFGHJKLZXCVBNM"; - - /* generate a new regcode */ - buf[13] = 0; - buf[0] = REGCODE_INITIAL[0]; - buf[1] = REGCODE_INITIAL[1]; - for( i = 2 ; i < 13 ; ++i ) - buf[i] = alphabet[random() % strlen(alphabet)]; - - getregfile(fpath); - if( (fd = open(fpath, O_WRONLY | O_CREAT, 0600)) == -1 ){ - perror("open"); - exit(1); - } - write(fd, buf, 13); - close(fd); - - return buf; -} - -static char * -getregcode(char *buf) -{ - int fd; - char fpath[PATHLEN]; - - getregfile(fpath); - if( (fd = open(fpath, O_RDONLY)) == -1 ){ - buf[0] = 0; - return buf; - } - read(fd, buf, 13); - close(fd); - buf[13] = 0; - return buf; -} - -void -delregcodefile(void) -{ - char fpath[PATHLEN]; - getregfile(fpath); - unlink(fpath); -} - -//////////////////////////////////////////////////////////////////////////// -// Justify Utilities -//////////////////////////////////////////////////////////////////////////// - -static void -justify_wait(char *userid, char *phone, char *career, - char *rname, char *addr, char *mobile) -{ - char buf[PATHLEN]; - sethomefile(buf, userid, FN_JUSTIFY_WAIT); - if (phone[0] != 0) { - FILE* fn = fopen(buf, "w"); - assert(fn); - fprintf(fn, "%s\n%s\ndummy\n%s\n%s\n%s\n", - phone, career, rname, addr, mobile); - fclose(fn); - } -} - -static void -email_justify(const userec_t *muser) -{ - char tmp[IDLEN + 1], buf[256], genbuf[256]; - /* - * It is intended to use BBSENAME instead of BBSNAME here. - * Because recently many poor users with poor mail clients - * (or evil mail servers) cannot handle/decode Chinese - * subjects (BBSNAME) correctly, so we'd like to use - * BBSENAME here to prevent subject being messed up. - * And please keep BBSENAME short or it may be truncated - * by evil mail servers. - */ - snprintf(buf, sizeof(buf), - " " BBSENAME " - [ %s ]", makeregcode(genbuf)); - - strlcpy(tmp, cuser.userid, sizeof(tmp)); - // XXX dirty, set userid=SYSOP - strlcpy(cuser.userid, str_sysop, sizeof(cuser.userid)); -#ifdef HAVEMOBILE - if (strcmp(muser->email, "m") == 0 || strcmp(muser->email, "M") == 0) - mobile_message(mobile, buf); - else -#endif - bsmtp("etc/registermail", buf, muser->email); - strlcpy(cuser.userid, tmp, sizeof(cuser.userid)); - move(20,0); - clrtobot(); - outs("§Ú̧Y±N±H¥X»{ÃÒ«H (±zÀ³¸Ó·|¦b 10 ¤ÀÄÁ¤º¦¬¨ì)\n" - "¦¬¨ì«á±z¥i¥H®Ú¾Ú»{ÃÒ«H¼ÐÃDªº»{ÃÒ½X\n" - "¿é¤J¨ì (U)ser -> (R)egister «á´N¥i¥H§¹¦¨µù¥U"); - pressanykey(); - return; -} - - -/* ¨Ï¥ÎªÌ¶ñ¼gµù¥Uªí®æ */ -static void -getfield(int line, const char *info, const char *desc, char *buf, int len) -{ - char prompt[STRLEN]; - char genbuf[200]; - - // clear first - move(line+1, 0); clrtoeol(); - move(line, 0); clrtoeol(); - prints(" ì¥ý³]©w¡G%-30.30s (%s)", buf, info); - snprintf(prompt, sizeof(prompt), " %s¡G", desc); - if (getdata_str(line + 1, 0, prompt, genbuf, len, DOECHO, buf)) - strcpy(buf, genbuf); - move(line+1, 0); clrtoeol(); - move(line, 0); clrtoeol(); - prints(" %s¡G%s", desc, buf); -} - - -int -setupnewuser(const userec_t *user) -{ - char genbuf[50]; - char *fn_fresh = ".fresh"; - userec_t utmp; - time_t clock; - struct stat st; - int fd, uid; - - clock = now; - - // XXX race condition... - if (dosearchuser(user->userid, NULL)) - { - vmsg("¤â¸}¤£°÷§Ö¡A§O¤H¤w¸g·m¨«¤F¡I"); - exit(1); - } - - /* Lazy method : ¥ý§ä´M¤w¸g²M°£ªº¹L´Á±b¸¹ */ - if ((uid = dosearchuser("", NULL)) == 0) { - /* ¨C 1 Ó¤p®É¡A²M²z user ±b¸¹¤@¦¸ */ - if ((stat(fn_fresh, &st) == -1) || (st.st_mtime < clock - 3600)) { - if ((fd = open(fn_fresh, O_RDWR | O_CREAT, 0600)) == -1) - return -1; - write(fd, ctime(&clock), 25); - close(fd); - log_usies("CLEAN", "dated users"); - - fprintf(stdout, "´M§ä·s±b¸¹¤¤, ½Ðµy«Ý¤ù¨è...\n\r"); - - if ((fd = open(fn_passwd, O_RDWR | O_CREAT, 0600)) == -1) - return -1; - - /* ¤£¾å±o¬°¤°»òn±q 2 ¶}©l... Ptt:¦]¬°SYSOP¦b1 */ - for (uid = 2; uid <= MAX_USERS; uid++) { - passwd_query(uid, &utmp); - // tolerate for one year. - check_and_expire_account(uid, &utmp, 365*12*60); - } - } - } - - /* initialize passwd semaphores */ - if (passwd_init()) - exit(1); - - passwd_lock(); - - uid = dosearchuser("", NULL); - if ((uid <= 0) || (uid > MAX_USERS)) { - passwd_unlock(); - vmsg("©êºp¡A¨Ï¥ÎªÌ±b¸¹¤w¸gº¡¤F¡AµLªkµù¥U·sªº±b¸¹"); - exit(1); - } - - setuserid(uid, user->userid); - snprintf(genbuf, sizeof(genbuf), "uid %d", uid); - log_usies("APPLY", genbuf); - - SHM->money[uid - 1] = user->money; - - if (passwd_update(uid, (userec_t *)user) == -1) { - passwd_unlock(); - vmsg("«Èº¡¤F¡A¦A¨£¡I"); - exit(1); - } - - passwd_unlock(); - - return uid; -} - -///////////////////////////////////////////////////////////////////////////// -// New Registration (Phase 1) -///////////////////////////////////////////////////////////////////////////// - -void -new_register(void) -{ - userec_t newuser; - char passbuf[STRLEN]; - int try, id, uid; - char *errmsg = NULL; - -#ifdef HAVE_USERAGREEMENT - more(HAVE_USERAGREEMENT, YEA); - while( 1 ){ - getdata(b_lines, 0, "½Ð°Ý±z±µ¨ü³o¥÷¨Ï¥ÎªÌ±ø´Ú¶Ü? (yes/no) ", - passbuf, 4, LCECHO); - if( passbuf[0] == 'y' ) - break; - if( passbuf[0] == 'n' ){ - vmsg("©êºp, ±z¶·n±µ¨ü¨Ï¥ÎªÌ±ø´Ú¤~¯àµù¥U±b¸¹¨É¨ü§Ú̪ºªA°Èò!"); - exit(1); - } - vmsg("½Ð¿é¤J yªí¥Ü±µ¨ü, nªí¥Ü¤£±µ¨ü"); - } -#endif - - // setup newuser - memset(&newuser, 0, sizeof(newuser)); - newuser.version = PASSWD_VERSION; - newuser.userlevel = PERM_DEFAULT; - newuser.uflag = BRDSORT_FLAG | MOVIE_FLAG; - newuser.uflag2 = 0; - newuser.firstlogin = newuser.lastlogin = now; - newuser.money = 0; - newuser.pager = PAGER_ON; - strlcpy(newuser.lasthost, fromhost, sizeof(newuser.lasthost)); - -#ifdef DBCSAWARE - if(u_detectDBCSAwareEvilClient()) - newuser.uflag &= ~DBCSAWARE_FLAG; - else - newuser.uflag |= DBCSAWARE_FLAG; -#endif - - more("etc/register", NA); - try = 0; - while (1) { - userec_t xuser; - int minute; - - if (++try >= 6) { - vmsg("±z¹Á¸Õ¿ù»~ªº¿é¤J¤Ó¦h¡A½Ð¤U¦¸¦A¨Ó§a"); - exit(1); - } - getdata(17, 0, msg_uid, newuser.userid, - sizeof(newuser.userid), DOECHO); - strcpy(passbuf, newuser.userid); - - if (bad_user_id(passbuf)) - outs("µLªk±µ¨ü³oÓ¥N¸¹¡A½Ð¨Ï¥Î^¤å¦r¥À¡A¨Ã¥B¤£n¥]§tªÅ®æ\n"); - else if ((id = getuser(passbuf, &xuser)) && - // >=: see check_and_expire_account definition - (minute = check_and_expire_account(id, &xuser, 0)) >= 0) - { - if (minute == 999999) // XXX magic number. It should be greater than MAX_USERS at least. - outs("¦¹¥N¸¹¤w¸g¦³¤H¨Ï¥Î ¬O¤£¦º¤§¨"); - else { - prints("¦¹¥N¸¹¤w¸g¦³¤H¨Ï¥Î ÁÙ¦³ %d ¤Ñ¤~¹L´Á \n", - minute / (60 * 24) + 1); - } - } else - break; - } - - // XXX °O±o³Ì«á create account «eÁÙn¦AÀˬd¤@¦¸ acc - - try = 0; - while (1) { - if (++try >= 6) { - vmsg("±z¹Á¸Õ¿ù»~ªº¿é¤J¤Ó¦h¡A½Ð¤U¦¸¦A¨Ó§a"); - exit(1); - } - move(19, 0); clrtoeol(); - outs(ANSI_COLOR(1;33) - "¬°ÁקK³Q°½¬Ý¡A±zªº±K½X¨Ã¤£·|Åã¥Ü¦bµe±¤W¡Aª½±µ¿é¤J§¹«á«ö Enter Áä§Y¥i¡C\n" - "¥t¥~½Ðª`·N±K½X¥u¦³«e¤KÓ¦r¤¸¦³®Ä¡A¶W¹Lªº±N¦Û°Ê©¿²¤¡C" - ANSI_RESET); - if ((getdata(18, 0, "½Ð³]©w±K½X¡G", passbuf, - sizeof(passbuf), NOECHO) < 3) || - !strcmp(passbuf, newuser.userid)) { - outs("±K½X¤Ó²³æ¡A©ö¾D¤J«I¡A¦Ü¤Ön 4 Ó¦r¡A½Ð«·s¿é¤J\n"); - continue; - } - strlcpy(newuser.passwd, passbuf, PASSLEN); - getdata(19, 0, "½ÐÀˬd±K½X¡G", passbuf, sizeof(passbuf), NOECHO); - if (strncmp(passbuf, newuser.passwd, PASSLEN)) { - outs("±K½X¿é¤J¿ù»~, ½Ð«·s¿é¤J±K½X.\n"); - continue; - } - passbuf[8] = '\0'; - strlcpy(newuser.passwd, genpasswd(passbuf), PASSLEN); - break; - } - // set-up more information. - - // warning: because currutmp=NULL, we can simply pass newuser.* to getdata. - // DON'T DO THIS IF YOUR currutmp != NULL. - try = 0; - while (strlen(newuser.nickname) < 2) - { - if (++try > 10) { - vmsg("±z¹Á¸Õ¿ù»~ªº¿é¤J¤Ó¦h¡A½Ð¤U¦¸¦A¨Ó§a"); - exit(1); - } - getdata(19, 0, "ºï¸¹¼ÊºÙ¡G", newuser.nickname, - sizeof(newuser.nickname), DOECHO); - } - - try = 0; - while (strlen(newuser.realname) < 4) - { - if (++try > 10) { - vmsg("±z¹Á¸Õ¿ù»~ªº¿é¤J¤Ó¦h¡A½Ð¤U¦¸¦A¨Ó§a"); - exit(1); - } - getdata(20, 0, "¯u¹ê©m¦W¡G", newuser.realname, - sizeof(newuser.realname), DOECHO); - - if ((errmsg = isvalidname(newuser.realname))) - { - memset(newuser.realname, 0, sizeof(newuser.realname)); - vmsg(errmsg); - } - } - - try = 0; - while (strlen(newuser.address) < 8) - { - // do not use isvalidaddr to check, - // because that requires foreign info. - if (++try > 10) { - vmsg("±z¹Á¸Õ¿ù»~ªº¿é¤J¤Ó¦h¡A½Ð¤U¦¸¦A¨Ó§a"); - exit(1); - } - getdata(21, 0, "Ápµ¸¦a§}¡G", newuser.address, - sizeof(newuser.address), DOECHO); - } - - try = 0; - while (newuser.year < 40) // magic number 40: see user.c - { - char birthday[sizeof("mmmm/yy/dd ")]; - int y, m, d; - - if (++try > 20) { - vmsg("±z¹Á¸Õ¿ù»~ªº¿é¤J¤Ó¦h¡A½Ð¤U¦¸¦A¨Ó§a"); - exit(1); - } - getdata(22, 0, "¥Í¤é (¦è¤¸¦~/¤ë/¤é, ¦p 1984/02/29)¡G", birthday, - sizeof(birthday), DOECHO); - - if (ParseDate(birthday, &y, &m, &d)) { - vmsg("¤é´Á®æ¦¡¤£¥¿½T"); - continue; - } else if (y < 1940) { - vmsg("§A¯uªº¦³¨º»ò¦Ñ¶Ü¡H"); - continue; - } - newuser.year = (unsigned char)(y-1900); - newuser.month = (unsigned char)m; - newuser.day = (unsigned char)d; - } - - setupnewuser(&newuser); - - if( (uid = initcuser(newuser.userid)) < 0) { - vmsg("µLªk«Ø¥ß±b¸¹"); - exit(1); - } - log_usies("REGISTER", fromhost); -} - -void -check_birthday(void) -{ - // check birthday - int changed = 0; - time_t t = (time_t)now; - struct tm tm; - - localtime_r(&t, &tm); - while ( cuser.year < 40 || // magic number 40: see user.c - cuser.year+3 > tm.tm_year) - { - char birthday[sizeof("mmmm/yy/dd ")]; - int y, m, d; - - clear(); - stand_title("¿é¤J¥Í¤é"); - move(2,0); - outs("¥»¯¸¬°°t¦X¹ê¦æ¤º®e¤À¯Å¨î«×¡A½Ð±z¿é¤J¥¿½Tªº¥Í¤é¸ê°T¡C"); - - getdata(5, 0, "¥Í¤é (¦è¤¸¦~/¤ë/¤é, ¦p 1984/02/29)¡G", birthday, - sizeof(birthday), DOECHO); - - if (ParseDate(birthday, &y, &m, &d)) { - vmsg("¤é´Á®æ¦¡¤£¥¿½T"); - continue; - } else if (y < 1940) { - vmsg("§A¯uªº¦³¨º»ò¦Ñ¶Ü¡H"); - continue; - } else if (y+3 > tm.tm_year+1900) { - vmsg("À¦¨à/¥¼¥X¥ÍÀ³¸ÓµLªk¨Ï¥Î BBS..."); - continue; - } - cuser.year = (unsigned char)(y-1900); - cuser.month = (unsigned char)m; - cuser.day = (unsigned char)d; - changed = 1; - } - - if (changed) { - clear(); - resolve_over18(); - } -} - -void -check_register(void) -{ - char fn[PATHLEN]; - - check_birthday(); - - if (HasUserPerm(PERM_LOGINOK)) - return; - - setuserfile(fn, FN_REJECT_NOTIFY); - - /* - * ÁקK¨Ï¥ÎªÌ³Q°h¦^µù¥U³æ«á¡A¦bª¾¹D°h¦^ªºì¦]¤§«e¡A - * ¤S°e¥X¤@¦¸µù¥U³æ¡C - */ - if (dashf(fn)) - { - more(fn, NA); - move(b_lines-3, 0); - outs("¤W¦¸µù¥U³æ¼f¬d¥¢±Ñ¡C\n" - "½Ð«·s¥Ó½Ð¨Ã·Ó¤W±«ü¥Ü¥¿½T¶ñ¼gµù¥U³æ¡C"); - while(getans("½Ð¿é¤J y Ä~Äò: ") != 'y'); - unlink(fn); - } else - if (ISNEWMAIL(currutmp)) - m_read(); - - if (!HasUserPerm(PERM_SYSOP)) { - /* ¦^ÂйL¨¥÷»{ÃÒ«H¨ç¡A©Î´¿¸g E-mail post ¹L */ - clear(); - move(9, 3); - outs("½Ð¸Ô¶ñ¼g" ANSI_COLOR(32) "µù¥U¥Ó½Ð³æ" ANSI_RESET "¡A" - "³q§i¯¸ªø¥HÀò±o¶i¶¥¨Ï¥ÎÅv¤O¡C\n\n\n\n"); - u_register(); - -#ifdef NEWUSER_LIMIT - if (cuser.lastlogin - cuser->firstlogin < 3 * 86400) - cuser.userlevel &= ~PERM_POST; - more("etc/newuser", YEA); -#endif - } -} - -///////////////////////////////////////////////////////////////////////////// -// User Registration (Phase 2) -///////////////////////////////////////////////////////////////////////////// - -static void -toregister(char *email, char *phone, char *career, - char *rname, char *addr, char *mobile) -{ - FILE *fn = NULL; - - justify_wait(cuser.userid, phone, career, rname, addr, mobile); - - clear(); - stand_title("»{ÃÒ³]©w"); - if (cuser.userlevel & PERM_NOREGCODE){ - strcpy(email, "x"); - goto REGFORM2; - } - move(1, 0); - outs("±z¦n, ¥»¯¸»{ÃÒ»{ÃÒªº¤è¦¡¦³:\n" - " 1.Y±z¦³ E-Mail (¥»¯¸¤£±µ¨ü yahoo, kimoµ¥§K¶Oªº E-Mail)\n" - " ½Ð¿é¤J±zªº E-Mail , §ÚÌ·|±Hµo§t¦³»{ÃÒ½Xªº«H¥óµ¹±z\n" - " ¦¬¨ì«á½Ð¨ì (U)ser => (R)egister ¿é¤J»{ÃÒ½X, §Y¥i³q¹L»{ÃÒ\n" - "\n" - " 2.Y±z¨S¦³ E-Mail ©Î¬O¤@ª½µLªk¦¬¨ì»{ÃÒ«H, ½Ð¿é¤J x \n" - " ·|¦³¯¸ªø¿Ë¦Û¤H¤u¼f®Öµù¥U¸ê®Æ¡A" ANSI_COLOR(1;33) - "¦ýª`·N³o¥i¯à·|ªá¤W¼Æ¶g©Î§ó¦h®É¶¡¡C" ANSI_RESET "\n" - "**********************************************************\n" - "* ª`·N! *\n" - "* ³q±`À³¸Ó·|¦b¿é¤J§¹¦¨«á¤Q¤ÀÄÁ¤º¦¬¨ì»{ÃÒ«H, Y¹L¤[¥¼¦¬¨ì *\n" - "* ½Ð¨ì¶l¥ó©U§£±íÀˬd¬O§_³Q·í§@©U§£«H(SPAM)¤F¡A¥t¥~Y¬O *\n" - "* ¿é¤J«áµo¥Í»{ÃÒ½X¿ù»~½Ð«¶ñ¤@¦¸ E-Mail *\n" - "**********************************************************\n"); - -#ifdef HAVEMOBILE - outs(" 3.Y±z¦³¤â¾÷ªù¸¹¥B·Q±Ä¨ú¤â¾÷²°T»{ÃÒªº¤è¦¡ , ½Ð¿é¤J m \n" - " §Ú̱N·|±Hµo§t¦³»{ÃÒ½XªºÂ²°Tµ¹±z \n" - " ¦¬¨ì«á½Ð¨ì(U)ser => (R)egister ¿é¤J»{ÃÒ½X, §Y¥i³q¹L»{ÃÒ\n"); -#endif - - while (1) { - email[0] = 0; - getfield(15, "¨¤À»{ÃÒ¥Î", "E-Mail Address", email, 50); - if (strcmp(email, "x") == 0 || strcmp(email, "X") == 0) - break; -#ifdef HAVEMOBILE - else if (strcmp(email, "m") == 0 || strcmp(email, "M") == 0) { - if (isvalidmobile(mobile)) { - char yn[3]; - getdata(16, 0, "½Ð¦A¦¸½T»{±z¿é¤Jªº¤â¾÷¸¹½X¥¿½T¹À? [y/N]", - yn, sizeof(yn), LCECHO); - if (yn[0] == 'Y' || yn[0] == 'y') - break; - } else { - move(15, 0); clrtobot(); - move(17, 0); - outs("«ü©wªº¤â¾÷¸¹½X¤£¥¿½T," - "Y±zµL¤â¾÷ªù¸¹½Ð¿ï¾Ü¨ä¥L¤è¦¡»{ÃÒ"); - } - - } -#endif - else if (isvalidemail(email)) { - char yn[3]; -#ifdef USE_EMAILDB - int email_count = emaildb_check_email(email, strlen(email)); - - if (email_count < 0) { - move(15, 0); clrtobot(); - move(17, 0); - outs("¼È®É¤£¤¹³\\ email »{ÃÒµù¥U, ½Ðµy«á¦A¸Õ\n"); - pressanykey(); - return; - } else if (email_count >= EMAILDB_LIMIT) { - move(15, 0); clrtobot(); - move(17, 0); - outs("«ü©wªº E-Mail ¤wµù¥U¹L¦h±b¸¹, ½Ð¨Ï¥Î¨ä¥L E-Mail, ©Î¿é¤J x ±Ä¤â°Ê»{ÃÒ\n"); - outs("¦ýª`·N¤â°Ê»{ÃÒ³q±`·|ªá¤W¼Æ¶g¥H¤Wªº®É¶¡¡C\n"); - } else { -#endif - getdata(16, 0, "½Ð¦A¦¸½T»{±z¿é¤Jªº E-Mail ¦ì¸m¥¿½T¹À? [y/N]", - yn, sizeof(yn), LCECHO); - if (yn[0] == 'Y' || yn[0] == 'y') - break; -#ifdef USE_EMAILDB - } -#endif - } else { - move(15, 0); clrtobot(); - move(17, 0); - outs("«ü©wªº E-Mail ¤£¥¿½T, Y±zµL E-Mail ½Ð¿é¤J x ¥Ñ¯¸ªø¤â°Ê»{ÃÒ\n"); - outs("¦ýª`·N¤â°Ê»{ÃÒ³q±`·|ªá¤W¼Æ¶g¥H¤Wªº®É¶¡¡C\n"); - } - } -#ifdef USE_EMAILDB - if (emaildb_update_email(cuser.userid, strlen(cuser.userid), - email, strlen(email)) < 0) { - move(15, 0); clrtobot(); - move(17, 0); - outs("¼È®É¤£¤¹³\\ email »{ÃÒµù¥U, ½Ðµy«á¦A¸Õ\n"); - pressanykey(); - return; - } -#endif - strlcpy(cuser.email, email, sizeof(cuser.email)); - REGFORM2: - if (strcasecmp(email, "x") == 0) { /* ¤â°Ê»{ÃÒ */ - if ((fn = fopen(fn_register, "a"))) { - fprintf(fn, "num: %d, %s", usernum, ctime4(&now)); - fprintf(fn, "uid: %s\n", cuser.userid); - fprintf(fn, "name: %s\n", rname); - fprintf(fn, "career: %s\n", career); - fprintf(fn, "addr: %s\n", addr); - fprintf(fn, "phone: %s\n", phone); - fprintf(fn, "mobile: %s\n", mobile); - fprintf(fn, "email: %s\n", email); - fprintf(fn, "----\n"); - fclose(fn); - // save justify information - snprintf(cuser.justify, sizeof(cuser.justify), - "%s:%s:<Manual>", phone, career); - } - // XXX what if we cannot open register form? - } else { - // register by mail of phone - snprintf(cuser.justify, sizeof(cuser.justify), - "%s:%s:<Email>", phone, career); -#ifdef HAVEMOBILE - if (phone != NULL && email[1] == 0 && tolower(email[0]) == 'm') - sprintf(cuser.justify, sizeof(cuser.justify), - "%s:%s:<Mobile>", phone, career); -#endif - email_justify(&cuser); - } -} - - -int -u_register(void) -{ - char rname[20], addr[50], mobile[16]; -#ifdef FOREIGN_REG - char fore[2]; -#endif - char phone[20], career[40], email[50], birthday[11], sex_is[2]; - unsigned char year, mon, day; - char inregcode[14], regcode[50]; - char ans[3], *ptr, *errcode; - char genbuf[200]; - FILE *fn; - - if (cuser.userlevel & PERM_LOGINOK) { - outs("±zªº¨¥÷½T»{¤w¸g§¹¦¨¡A¤£»Ý¶ñ¼g¥Ó½Ðªí"); - return XEASY; - } - if ((fn = fopen(fn_register, "r"))) { - int i =0; - while (fgets(genbuf, STRLEN, fn)) { - if ((ptr = strchr(genbuf, '\n'))) - *ptr = '\0'; - if (strncmp(genbuf, "uid: ", 5) != 0) - continue; - i++; - if(strcmp(genbuf + 5, cuser.userid) != 0) - continue; - fclose(fn); - /* idiots complain about this, so bug them */ - clear(); - move(3, 0); - prints(" ±zªºµù¥U¥Ó½Ð³æ©|¦b³B²z¤¤(³B²z¶¶¦ì: %d)¡A½Ð@¤ßµ¥Ô\n\n", i); - outs(" ¦pªG±z¤w¦¬¨ìµù¥U½X«o¬Ý¨ì³oÓµe±¡A¨º¥Nªí±z¦b¨Ï¥Î Email µù¥U«á\n"); - outs(" " ANSI_COLOR(1;31) "¤S¥t¥~¥Ó½Ð¤F¯¸ªøª½±µ¤H¤u¼f®Öªºµù¥U¥Ó½Ð³æ¡C" - ANSI_RESET "\n\n"); - // outs("¸Ó¦º¡A³£¤£¬Ý»¡©úªº...\n"); - outs(" ¶i¤J¤H¤u¼f®Öµ{§Ç«á Email µù¥U¦Û°Ê¥¢®Ä¡A¦³µù¥U½X¤]¨S¥Î¡A\n"); - outs(" nµ¥¨ì¼f®Ö§¹¦¨ (·|¦hªá«Ü¦h®É¶¡¡A³q±`°_½X¼Æ¤Ñ) ¡A©Ò¥H½Ð@¤ßµ¥Ô¡C\n\n"); - - /* ¤U±¬O°ê¤ýªº code ©Ò»Ýnªº message */ -#if 0 - outs(" ¥t¥~½Ðª`·N¡AY¯¸ªø¼fµù¥U³æ®É±z¥¿¦b¯¸¤W«h·|µLªk¼f®Ö¡B¦Û°Ê¸õ¹L¡C\n"); - outs(" ©Ò¥Hµ¥Ô¼f®Ö®É½Ð¤Å±¾¯¸¡CY¶W¹L¨â¤T¤Ñ¤´¥¼³Q¼f¨ì¡A³q±`´N¬O³oÓì¦]¡C\n"); -#endif - - vmsg("±zªºµù¥U¥Ó½Ð³æ©|¦b³B²z¤¤"); - return FULLUPDATE; - } - fclose(fn); - } - strlcpy(rname, cuser.realname, sizeof(rname)); - strlcpy(addr, cuser.address, sizeof(addr)); - strlcpy(email, cuser.email, sizeof(email)); - if (cuser.mobile) - snprintf(mobile, sizeof(mobile), "0%09d", cuser.mobile); - else - mobile[0] = 0; - if (cuser.month == 0 && cuser.day == 0 && cuser.year == 0) - birthday[0] = 0; - else - snprintf(birthday, sizeof(birthday), "%04i/%02i/%02i", - 1900 + cuser.year, cuser.month, cuser.day); - sex_is[0] = (cuser.sex % 8) + '1'; - sex_is[1] = 0; - career[0] = phone[0] = '\0'; - sethomefile(genbuf, cuser.userid, FN_JUSTIFY_WAIT); - if ((fn = fopen(genbuf, "r"))) { - fgets(genbuf, sizeof(genbuf), fn); - chomp(genbuf); - strlcpy(phone, genbuf, sizeof(phone)); - - fgets(genbuf, sizeof(genbuf), fn); - chomp(genbuf); - strlcpy(career, genbuf, sizeof(career)); - - fgets(genbuf, sizeof(genbuf), fn); // old version compatible - - fgets(genbuf, sizeof(genbuf), fn); - chomp(genbuf); - strlcpy(rname, genbuf, sizeof(rname)); - - fgets(genbuf, sizeof(genbuf), fn); - chomp(genbuf); - strlcpy(addr, genbuf, sizeof(addr)); - - fgets(genbuf, sizeof(genbuf), fn); - chomp(genbuf); - strlcpy(mobile, genbuf, sizeof(mobile)); - - fclose(fn); - } - - if (cuser.userlevel & PERM_NOREGCODE) { - vmsg("±z¤£³Q¤¹³\\¨Ï¥Î»{ÃÒ½X»{ÃÒ¡C½Ð¶ñ¼gµù¥U¥Ó½Ð³æ"); - goto REGFORM; - } - - // getregcode(regcode); - - // XXX why check by year? - // birthday is moved to earlier, so let's check email instead. - if (cuser.email[0] && // cuser.year != 0 && /* ¤w¸g²Ä¤@¦¸¶ñ¹L¤F~ ^^" */ - strcmp(cuser.email, "x") != 0 && /* ¤W¦¸¤â°Ê»{ÃÒ¥¢±Ñ */ - strcmp(cuser.email, "X") != 0) - { - clear(); - stand_title("EMail»{ÃÒ"); - move(2, 0); - - prints("½Ð¿é¤J±zªº»{ÃÒ½X¡C(¥Ñ %s ¶}ÀYµLªÅ¥Õªº¤Q¤T½X)\n" - "©Î¿é¤J x ¨Ó«·s¶ñ¼g E-Mail ©Î§ï¥Ñ¯¸ªø¤â°Ê»{ÃÒ\n", REGCODE_INITIAL); - inregcode[0] = 0; - - do{ - getdata(10, 0, "±zªº»{ÃÒ½X¡G", - inregcode, sizeof(inregcode), DOECHO); - if( strcmp(inregcode, "x") == 0 || strcmp(inregcode, "X") == 0 ) - break; - if( strlen(inregcode) != 13 || inregcode[0] == ' ') - vmsg("»{ÃÒ½X¿é¤J¤£§¹¾ã¡AÁ`¦@À³¦³¤Q¤T½X¡A¨S¦³ªÅ¥Õ¦r¤¸¡C"); - else if( inregcode[0] != REGCODE_INITIAL[0] || inregcode[1] != REGCODE_INITIAL[1] ) { - /* old regcode */ - vmsg("¿é¤Jªº»{ÃÒ½X¿ù»~¡A" // "©Î¦]¨t²Îª@¯Å¤w¥¢®Ä¡A" - "½Ð¿é¤J x «¶ñ¤@¦¸ E-Mail"); - } - else - break; - } while( 1 ); - - // make it case insensitive. - if (strcasecmp(inregcode, getregcode(regcode)) == 0) { - int unum; - delregcodefile(); - if ((unum = searchuser(cuser.userid, NULL)) == 0) { - vmsg("¨t²Î¿ù»~¡A¬dµL¦¹¤H¡I"); - u_exit("getuser error"); - exit(0); - } - mail_muser(cuser, "[µù¥U¦¨¥\\Åo]", "etc/registeredmail"); -#if FOREIGN_REG_DAY > 0 - if(cuser.uflag2 & FOREIGN) - mail_muser(cuser, "[¥X¤J¹ÒºÞ²z§½]", "etc/foreign_welcome"); -#endif - cuser.userlevel |= (PERM_LOGINOK | PERM_POST); - outs("\nµù¥U¦¨¥\\, «·s¤W¯¸«á±N¨ú±o§¹¾ãÅv\n" - "½Ð«ö¤U¥ô¤@Áä¸õÂ÷«á«·s¤W¯¸~ :)"); - sethomefile(genbuf, cuser.userid, FN_JUSTIFY_WAIT); - unlink(genbuf); - snprintf(cuser.justify, sizeof(cuser.justify), - "%s:%s:email", phone, career); - sethomefile(genbuf, cuser.userid, FN_JUSTIFY); - log_file(genbuf, LOG_CREAT, cuser.justify); - pressanykey(); - u_exit("registed"); - exit(0); - return QUIT; - } else if (strcasecmp(inregcode, "x") != 0) { - if (regcode[0]) - { - vmsg("»{ÃÒ½X¿ù»~¡I"); - return FULLUPDATE; - } - else - { - vmsg("»{ÃÒ½X¤w¹L´Á¡A½Ð«·sµù¥U¡C"); - toregister(email, phone, career, rname, addr, mobile); - return FULLUPDATE; - } - } else { - toregister(email, phone, career, rname, addr, mobile); - return FULLUPDATE; - } - } - - REGFORM: - getdata(b_lines - 1, 0, "±z½T©wn¶ñ¼gµù¥U³æ¶Ü(Y/N)¡H[N] ", - ans, 3, LCECHO); - if (ans[0] != 'y') - return FULLUPDATE; - - move(2, 0); - clrtobot(); - while (1) { - clear(); - move(1, 0); - prints("%s(%s) ±z¦n¡A½Ð¾Ú¹ê¶ñ¼g¥H¤Uªº¸ê®Æ:", - cuser.userid, cuser.nickname); -#ifdef FOREIGN_REG - fore[0] = 'y'; - fore[1] = 0; - getfield(2, "Y/n", "¬O§_²{¦b¦í¦b¥xÆW", fore, 2); - if (fore[0] == 'n') - fore[0] |= FOREIGN; - else - fore[0] = 0; -#endif - while (1) { - getfield(8, -#ifdef FOREIGN_REG - "½Ð¥Î¥»¦W", -#else - "½Ð¥Î¤¤¤å", -#endif - "¯u¹ê©m¦W", rname, 20); - if( (errcode = isvalidname(rname)) == NULL ) - break; - else - vmsg(errcode); - } - - move(11, 0); - outs(" ½ÐºÉ¶q¸Ô²Óªº¶ñ¼g±zªºªA°È³æ¦ì¡A¤j±M°|®Õ½Ð³Â·Ð" - "¥[" ANSI_COLOR(1;33) "¨t©Ò" ANSI_RESET "¡A¤½¥q³æ¦ì½Ð¥[" ANSI_COLOR(1;33) "¾ºÙ" ANSI_RESET "¡A\n" - " ¼ÈµL¤u§@½Ð³Â·Ð¶ñ¼g" ANSI_COLOR(1;33) "²¦·~¾Ç®Õ" ANSI_RESET "¡C\n"); - while (1) { - getfield(9, "(²¦·~)¾Ç®Õ(§t" ANSI_COLOR(1;33) "¨t©Ò¦~¯Å" ANSI_RESET ")©Î³æ¦ì¾ºÙ", - "ªA°È³æ¦ì", career, 40); - if( (errcode = isvalidcareer(career)) == NULL ) - break; - else - vmsg(errcode); - } - move(10, 0); clrtobot(); - while (1) { - getfield(10, "§t" ANSI_COLOR(1;33) "¿¤¥«" ANSI_RESET "¤Îªù¹ì¸¹½X" - "(¥x¥_½Ð¥[" ANSI_COLOR(1;33) "¦æ¬F°Ï" ANSI_RESET ")", - "¥Ø«e¦í§}", addr, sizeof(addr)); - if( (errcode = isvalidaddr(addr)) == NULL -#ifdef FOREIGN_REG - || fore[0] -#endif - ) - break; - else - vmsg(errcode); - } - while (1) { - getfield(11, "¤£¥[-(), ¥]¬Aªø³~°Ï¸¹", "³sµ¸¹q¸Ü", phone, 11); - if( (errcode = isvalidphone(phone)) == NULL ) - break; - else - vmsg(errcode); - } - getfield(12, "¥u¿é¤J¼Æ¦r ¦p:0912345678 (¥i¤£¶ñ)", - "¤â¾÷¸¹½X", mobile, 20); - while (1) { - getfield(13, "¦è¤¸/¤ë¤ë/¤é¤é ¦p:1984/02/29", "¥Í¤é", birthday, sizeof(birthday)); - if (birthday[0] == 0) { - snprintf(birthday, sizeof(birthday), "%04i/%02i/%02i", - 1900 + cuser.year, cuser.month, cuser.day); - mon = cuser.month; - day = cuser.day; - year = cuser.year; - } else { - int y, m, d; - if (ParseDate(birthday, &y, &m, &d)) { - vmsg("±zªº¿é¤J¤£¥¿½T"); - continue; - } - mon = (unsigned char)m; - day = (unsigned char)d; - year = (unsigned char)(y - 1900); - } - if (year < 40) { - vmsg("±zªº¿é¤J¤£¥¿½T"); - continue; - } - break; - } - getfield(14, "1.¸¯®æ 2.©j±µ ", "©Ê§O", sex_is, 2); - getdata(20, 0, "¥H¤W¸ê®Æ¬O§_¥¿½T(Y/N)¡H(Q)¨ú®øµù¥U [N] ", - ans, 3, LCECHO); - if (ans[0] == 'q') - return 0; - if (ans[0] == 'y') - break; - } - strlcpy(cuser.realname, rname, sizeof(cuser.realname)); - strlcpy(cuser.address, addr, sizeof(cuser.address)); - strlcpy(cuser.email, email, sizeof(cuser.email)); - cuser.mobile = atoi(mobile); - cuser.sex = (sex_is[0] - '1') % 8; - cuser.month = mon; - cuser.day = day; - cuser.year = year; -#ifdef FOREIGN_REG - if (fore[0]) - cuser.uflag2 |= FOREIGN; - else - cuser.uflag2 &= ~FOREIGN; -#endif - trim(career); - trim(addr); - trim(phone); - - toregister(email, phone, career, rname, addr, mobile); - - // update cuser - passwd_update(usernum, &cuser); - - return FULLUPDATE; -} - -///////////////////////////////////////////////////////////////////////////// -// Administration (SYSOP Validation) -///////////////////////////////////////////////////////////////////////////// - -#define REJECT_REASONS (6) -#define REASON_LEN (60) -static const char *reasonstr[REJECT_REASONS] = { - "¿é¤J¯u¹ê©m¦W", - "¸Ô¶ñ(²¦·~)¾Ç®Õ¡y¨t¡z¡y¯Å¡z©ÎªA°È³æ¦ì(§t©ÒÄÝ¿¤¥«¤Î¾ºÙ)", - "¶ñ¼g§¹¾ãªº¦í§}¸ê®Æ (§t¿¤¥«¦WºÙ, ¥x¥_¥«½Ð§t¦æ¬F°Ï°ì)", - "¸Ô¶ñ³sµ¸¹q¸Ü (§t°Ï½X, ¤¤¶¡¤£¥[ '-', '(', ')' µ¥²Å¸¹)", - "ºë½T¨Ã§¹¾ã¶ñ¼gµù¥U¥Ó½Ðªí", - "¥Î¤¤¤å¶ñ¼g¥Ó½Ð³æ", -}; - -#define REASON_FIRSTABBREV '0' -#define REASON_IN_ABBREV(x) \ - ((x) >= REASON_FIRSTABBREV && (x) - REASON_FIRSTABBREV < REJECT_REASONS) -#define REASON_EXPANDABBREV(x) reasonstr[(x) - REASON_FIRSTABBREV] - -void -regform_accept(const char *userid, const char *justify) -{ - char buf[PATHLEN]; - int unum = 0; - userec_t muser; - - unum = getuser(userid, &muser); - if (unum == 0) - return; // invalid user - - muser.userlevel |= (PERM_LOGINOK | PERM_POST); - strlcpy(muser.justify, justify, sizeof(muser.justify)); - // manual accept sets email to 'x' - strlcpy(muser.email, "x", sizeof(muser.email)); - - // handle files - sethomefile(buf, muser.userid, FN_JUSTIFY_WAIT); - unlink(buf); - sethomefile(buf, muser.userid, FN_REJECT_NOTIFY); - unlink(buf); - sethomefile(buf, muser.userid, FN_JUSTIFY); - log_filef(buf, LOG_CREAT, "%s\n", muser.justify); - - // update password file - passwd_update(unum, &muser); - - // alert online users? - sendalert(muser.userid, ALERT_PWD_PERM|ALERT_PWD_JUSTIFY); // force to reload perm - -#if FOREIGN_REG_DAY > 0 - if(muser.uflag2 & FOREIGN) - mail_muser(muser, "[¥X¤J¹ÒºÞ²z§½]", "etc/foreign_welcome"); - else -#endif - // last: send notification mail - mail_muser(muser, "[µù¥U¦¨¥\\Åo]", "etc/registered"); -} - -void -regform_reject(const char *userid, const char *reason) -{ - char buf[PATHLEN]; - FILE *fp = NULL; - int unum = 0; - userec_t muser; - - unum = getuser(userid, &muser); - if (unum == 0) - return; // invalid user - - muser.userlevel &= ~(PERM_LOGINOK | PERM_POST); - - // handle files - sethomefile(buf, muser.userid, FN_JUSTIFY_WAIT); - unlink(buf); - - // update password file - passwd_update(unum, &muser); - - // alert notify users? - sendalert(muser.userid, ALERT_PWD_PERM); // force to reload perm - - // last: send notification - mkuserdir(muser.userid); - sethomefile(buf, muser.userid, FN_REJECT_NOTIFY); - fp = fopen(buf, "wt"); - assert(fp); - syncnow(); - fprintf(fp, "%s µù¥U¥¢±Ñ¡C\n", Cdate(&now)); - - // multiple abbrev loop - if (REASON_IN_ABBREV(reason[0])) - { - int i = 0; - for (i = 0; i < REASON_LEN && REASON_IN_ABBREV(reason[i]); i++) - fprintf(fp, "[°h¦^ì¦]] ½Ð%s\n", REASON_EXPANDABBREV(reason[i])); - } else { - fprintf(fp, "[°h¦^ì¦]] %s\n", reason); - } - fclose(fp); - mail_muser(muser, "[µù¥U¥¢±Ñ]", buf); -} - -// Regform v1 API -// read count entries from regsrc to a temp buffer -FILE * -pull_regform(const char *regfile, char *workfn, int count) -{ - FILE *fp = NULL; - - snprintf(workfn, PATHLEN, "%s.tmp", regfile); - if (dashf(workfn)) { - vmsg("¨ä¥L SYSOP ¤]¦b¼f®Öµù¥U¥Ó½Ð³æ"); - return NULL; - } - - // count < 0 means unlimited pulling - Rename(regfile, workfn); - if ((fp = fopen(workfn, "r")) == NULL) { - vmsgf("¨t²Î¿ù»~¡AµLªkŪ¨úµù¥U¸ê®ÆÀÉ: %s", workfn); - return NULL; - } - return fp; -} - -// write all left in "remains" to regfn. -void -pump_regform(const char *regfn, FILE *remains) -{ - // restore trailing tickets - char buf[PATHLEN]; - FILE *fout = fopen(regfn, "at"); - if (!fout) - return; - - while (fgets(buf, sizeof(buf), remains)) - fputs(buf, fout); - fclose(fout); -} - -// New Regform UI -static void -prompt_regform_ui() -{ - move(b_lines, 0); - outs(ANSI_COLOR(30;47) " " - ANSI_COLOR(31) "y" ANSI_COLOR(30) "±µ¨ü " - ANSI_COLOR(31) "n" ANSI_COLOR(30) "©Úµ´ " - ANSI_COLOR(31) "d" ANSI_COLOR(30) "§R°£ " - ANSI_COLOR(31) "s" ANSI_COLOR(30) "¸õ¹L " - ANSI_COLOR(31) "u" ANSI_COLOR(30) "´_ì " - " " - ANSI_COLOR(31) "0-9jk¡ô¡õ" ANSI_COLOR(30) "²¾°Ê " - ANSI_COLOR(31) "ªÅ¥Õ/PgDn" ANSI_COLOR(30) "Àx¦s+¤U¶ " - " " - ANSI_COLOR(31) "q/END" ANSI_COLOR(30) "µ²§ô " - ANSI_RESET); -} - -static void -resolve_reason(char *s, int y) -{ - // should start with REASON_FIRSTABBREV - const char *reason_prompt = - " (0)¯u¹ê©m¦W (1)¸Ô¶ñ¨t¯Å (2)§¹¾ã¦í§}" - " (3)¸Ô¶ñ¹q¸Ü (4)½T¹ê¶ñ¼g (5)¤¤¤å¶ñ¼g"; - - s[0] = 0; - move(y, 0); - outs(reason_prompt); outs("\n"); - - do { - getdata(y+1, 0, - "°h¦^ì¦]: ", s, REASON_LEN, DOECHO); - - // convert abbrev reasons (format: single digit, or multiple digites) - if (REASON_IN_ABBREV(s[0])) - { - if (s[1] == 0) // simple replace ment - { - strlcpy(s+2, REASON_EXPANDABBREV(s[0]), - REASON_LEN-2); - s[0] = 0xbd; // '½Ð'[0]; - s[1] = 0xd0; // '½Ð'[1]; - } else { - // strip until all digites - char *p = s; - while (*p) - { - if (!REASON_IN_ABBREV(*p)) - *p = ' '; - p++; - } - strip_blank(s, s); - strlcat(s, " [¦h«ì¦]]", REASON_LEN); - } - } - - if (strlen(s) < 4) - { - if (vmsg("ì¦]¤Óµu¡C n¨ú®ø°h¦^¶Ü¡H (y/N): ") == 'y') - { - *s = 0; - return; - } - } - } while (strlen(s) < 4); -} - -//////////////////////////////////////////////////////////////////////////// -// Regform Utilities -//////////////////////////////////////////////////////////////////////////// - -// TODO define and use structure instead, even in reg request file. -typedef struct { - // current format: - // (optional) num: unum, date - // [0] uid: xxxxx (IDLEN=12) - // [1] name: RRRRRR (20) - // [2] career: YYYYYYYYYYYYYYYYYYYYYYYYYY (40) - // [3] addr: TTTTTTTTT (50) - // [4] phone: 02DDDDDDDD (20) - // [5] email: x (50) (deprecated) - // [6] mobile: (deprecated) - // [7] ---- - // lasthost: 16 - char userid[IDLEN+1]; - - char exist; - char online; - char pad [ 5]; // IDLEN(12)+1+1+1+5=20 - - char name [20]; - char career[40]; - char addr [50]; - char phone [20]; -} RegformEntry; - -// regform format utilities -int -load_regform_entry(RegformEntry *pre, FILE *fp) -{ - char buf[STRLEN]; - char *v; - - memset(pre, 0, sizeof(RegformEntry)); - while (fgets(buf, sizeof(buf), fp)) - { - if (buf[0] == '-') - break; - buf[sizeof(buf)-1] = 0; - v = strchr(buf, ':'); - if (v == NULL) - continue; - *v++ = 0; - if (*v == ' ') v++; - chomp(v); - - if (strcmp(buf, "uid") == 0) - strlcpy(pre->userid, v, sizeof(pre->userid)); - else if (strcmp(buf, "name") == 0) - strlcpy(pre->name, v, sizeof(pre->name)); - else if (strcmp(buf, "career") == 0) - strlcpy(pre->career, v, sizeof(pre->career)); - else if (strcmp(buf, "addr") == 0) - strlcpy(pre->addr, v, sizeof(pre->addr)); - else if (strcmp(buf, "phone") == 0) - strlcpy(pre->phone, v, sizeof(pre->phone)); - } - return pre->userid[0] ? 1 : 0; -} - -int -print_regform_entry(const RegformEntry *pre, FILE *fp, int close) -{ - fprintf(fp, "uid: %s\n", pre->userid); - fprintf(fp, "name: %s\n", pre->name); - fprintf(fp, "career: %s\n", pre->career); - fprintf(fp, "addr: %s\n", pre->addr); - fprintf(fp, "phone: %s\n", pre->phone); - if (close) - fprintf(fp, "----\n"); - return 1; -} - -int -append_regform(const RegformEntry *pre, const char *logfn, - const char *varname, const char *varval1, const char *varval2) -{ - FILE *fout = fopen(logfn, "at"); - if (!fout) - return 0; - - print_regform_entry(pre, fout, 0); - if (varname && *varname) - { - syncnow(); - fprintf(fout, "Date: %s\n", Cdate(&now)); - if (!varval1) varval1 = ""; - fprintf(fout, "%s: %s", varname, varval1); - if (varval2) fprintf(fout, " %s", varval2); - fprintf(fout, "\n"); - } - // close it - fprintf(fout, "----\n"); - fclose(fout); - return 1; -} - -//////////////////////////////////////////////////////////////////////////// -// Regform2 API -//////////////////////////////////////////////////////////////////////////// - -// registration queue -int -regq_append(const char *userid) -{ - if (file_append_record(FN_REQLIST, userid) < 0) - return 0; - return 1; -} - -int -regq_find(const char *userid) -{ - return file_find_record(FN_REQLIST, userid); -} - -int -regq_delete(const char *userid) -{ - return file_delete_record(FN_REQLIST, userid, 0); -} - -// user home regform operation -int -regfrm_exist(const char *userid) -{ - char fn[PATHLEN]; - sethomefile(fn, userid, FN_REGFORM); - return dashf(fn) ? 1 : 0; -} - -int -regfrm_load(const char *userid, RegformEntry *pre) -{ - FILE *fp = NULL; - char fn[PATHLEN]; - int ret = 0; - sethomefile(fn, userid, FN_REGFORM); - if (!dashf(fn)) - return 0; - - fp = fopen(fn, "rt"); - if (!fp) - return 0; - ret = load_regform_entry(pre, fp); - fclose(fp); - return ret; -} - -int -regfrm_save(const char *userid, const RegformEntry *pre) -{ - FILE *fp = NULL; - char fn[PATHLEN]; - int ret = 0; - sethomefile(fn, userid, FN_REGFORM); - - fp = fopen(fn, "wt"); - if (!fp) - return 0; - ret = print_regform_entry(pre, fp, 1); - fclose(fp); - return ret; -} - -int -regfrm_trylock(const char *userid) -{ - int fd = 0; - char fn[PATHLEN]; - sethomefile(fn, userid, FN_REGFORM); - if (!dashf(fn)) return 0; - fd = open(fn, O_RDONLY); - if (fd < 0) return 0; - if (flock(fd, LOCK_EX|LOCK_NB) == 0) - return fd; - close(fd); - return 0; -} - -int -regfrm_unlock(int lockfd) -{ - int fd = lockfd; - if (lockfd <= 0) - return 0; - lockfd = flock(fd, LOCK_UN) == 0 ? 1 : 0; - close(fd); - return lockfd; -} - -// regform processors -int -regfrm_accept(RegformEntry *pre) -{ - char justify[REGLEN+1], buf[STRLEN*2]; - char fn[PATHLEN], fnlog[PATHLEN]; - - // dry run! - vmsg("regfrm_accept"); - return 1; - - sethomefile(fn, pre->userid, FN_REGFORM); - - // build justify string - removespace(pre->phone); - removespace(pre->career); - snprintf(justify, sizeof(justify), - "%s:%s:%s", pre->phone, pre->career, cuser.userid); - - // call handler - regform_accept(pre->userid, justify); - - // append current form to history. - sethomefile(fnlog, pre->userid, FN_REGFORM_LOG); - AppendTail(fn, fnlog, 0); - // global history - snprintf(buf, sizeof(buf), "Approved: %s -> %s\nDate: %s\n", - cuser.userid, pre->userid, Cdate(&now)); - file_append_line(FN_REGISTER_LOG, buf); - AppendTail(fn, FN_REGISTER_LOG, 0); - - // remove from queue - unlink(fn); - regq_delete(pre->userid); - return 1; -} - -int -regfrm_reject(RegformEntry *pre, const char *reason) -{ - char buf[STRLEN*2]; - char fn[PATHLEN]; - - // dry run! - vmsg("regfrm_reject"); - return 1; - - sethomefile(fn, pre->userid, FN_REGFORM); - - // call handler - regform_reject(pre->userid, reason); - - // log it - snprintf(buf, sizeof(buf), "Rejected: %s -> %s [%s]\nDate: %s\n", - cuser.userid, pre->userid, reason, Cdate(&now)); - file_append_line(FN_REGISTER_LOG, buf); - AppendTail(fn, FN_REGISTER_LOG, 0); - - // remove from queue - unlink(fn); - regq_delete(pre->userid); - return 1; -} - -int -regfrm_delete(const char *userid) -{ - char fn[PATHLEN]; - sethomefile(fn, userid, FN_REGFORM); - - // dry run! - vmsgf("regfrm_delete (%s)", userid); - return 1; - - // directly delete. - unlink(fn); - - // remove from queue - regq_delete(userid); - return 1; -} - -// working queue -FILE * -regq_init_pull() -{ - FILE *fp = tmpfile(), *src =NULL; - char buf[STRLEN]; - if (!fp) return NULL; - src = fopen(FN_REQLIST, "rt"); - if (!src) { fclose(fp); return NULL; } - while (fgets(buf, sizeof(buf), src)) - fputs(buf, fp); - fclose(src); - rewind(fp); - return fp; -} - -int -regq_pull(FILE *fp, char *uid) -{ - char buf[STRLEN]; - size_t idlen = 0; - uid[0] = 0; - if (fgets(buf, sizeof(buf), fp) == NULL) - return 0; - idlen = strcspn(buf, str_space); - if (idlen < 1) return 0; - if (idlen > IDLEN) idlen = IDLEN; - strlcpy(uid, buf, idlen+1); - return 1; -} - -int -regq_end_pull(FILE *fp) -{ - // no need to unlink because fp is a tmpfile. - if (!fp) return 0; - fclose(fp); - return 1; -} - -// UI part -int -ui_display_regform_single( - const userec_t *xuser, - const RegformEntry *pre, - int tid, char *reason) -{ - int c; - - while (1) - { - move(1, 0); - user_display(xuser, 1); - move(14, 0); - prints(ANSI_COLOR(1;32) - "--------------- ³o¬O²Ä %2d ¥÷µù¥U³æ ------------------" - ANSI_RESET "\n", tid); - prints(" %-12s: %s\n", "±b¸¹", pre->userid); - prints("0.%-12s: %s%s\n", "¯u¹ê©m¦W", pre->name, - xuser->uflag2 & FOREIGN ? " (¥~Äy)" : - ""); - prints("1.%-12s: %s\n", "ªA°È³æ¦ì", pre->career); - prints("2.%-12s: %s\n", "¥Ø«e¦í§}", pre->addr); - prints("3.%-12s: %s\n", "³sµ¸¹q¸Ü", pre->phone); - - move(b_lines, 0); - outs("¬O§_±µ¨ü¦¹¸ê®Æ(Y/N/Q/Del/Skip)¡H[S] "); - - c = tolower(igetch() & 0xFF); // round to ASCII - if (c == 'y' || c == 'q' || c == 'd' || c == 's') - return c; - if (c == 'n') - { - int n = 0; - move(3, 0); - outs("\n" ANSI_COLOR(1;31) - "½Ð´£¥X°h¦^¥Ó½Ðªíì¦]¡A«ö <Enter> ¨ú®ø:\n" ANSI_RESET); - for (n = 0; n < REJECT_REASONS; n++) - prints("%d) ½Ð%s\n", n, reasonstr[n]); - outs("\n\n\n"); // preserved for prompt - - getdata(3+2+REJECT_REASONS+1, 0,"°h¦^ì¦]: ", - reason, REASON_LEN, DOECHO); - if (reason[0] == 0) - continue; - // interprete reason - return 'n'; - } - else if (REASON_IN_ABBREV(c)) - { - // quick set - sprintf(reason, "%c", c); - return 'n'; - } - return 's'; - } - // shall never reach here - return 's'; -} - -// sample validator -void -regform2_validate_single() -{ - int lfd = 0; - int tid = 0; - char uid[IDLEN+1]; - char rsn[REASON_LEN]; - FILE *fpregq = regq_init_pull(); - RegformEntry re; - - if (!fpregq) - return; - - while (regq_pull(fpregq, uid)) - { - userec_t muser; - int unum = 0; - int abort = 0; - - // check if user exists. - memset(&muser, 0, sizeof(muser)); - unum = getuser(uid, &muser); - - if (unum < 1) - { - regq_delete(uid); - continue; - } - - // check if regform exists. - if (!regfrm_exist(uid)) - { - // TODO delete here? - regq_delete(uid); - continue; - } - - // TODO check if user is already registered -#if 0 - if (muser.userlevel & PERM_LOGINOK) - { - regfrm_delete(uid); - continue; - } -#endif - - // try to lock - lfd = regfrm_trylock(uid); - if (lfd <= 0) - continue; - - // load it - if (!regfrm_load(uid, &re)) - { - regfrm_delete(uid); - regfrm_unlock(lfd); - // regq_delete(uid); // done in regfrm_delete - continue; - } - - tid ++; - // display regform and process - switch(ui_display_regform_single(&muser, &re, tid, rsn)) - { - case 'a': // accept - regfrm_accept(&re); - break; - - case 'd': // delete - regfrm_delete(uid); - break; - - case 'q': // quit - abort = 1; - break; - - case 'n': // reject - regfrm_reject(&re, rsn); - break; - - case 's': // skip - // do nothing. - break; - - default: // shall never reach here - assert(0); - break; - } - - // final processing - regfrm_unlock(lfd); - - if (abort) - break; - } - regq_end_pull(fpregq); - - // finishing - clear(); move(5, 0); - prints("±z¼f¤F %d ¥÷µù¥U³æ¥÷¡C", tid); - pressanykey(); -} - -#define FORMS_IN_PAGE (10) - -int -regform2_validate_page(int dryrun) -{ - int unum = 0; - int yMsg = FORMS_IN_PAGE*2+1; - userec_t muser; - RegformEntry forms [FORMS_IN_PAGE]; - char ans [FORMS_IN_PAGE]; - int lfds [FORMS_IN_PAGE]; - char rejects[FORMS_IN_PAGE][REASON_LEN]; // reject reason length - char rsn [REASON_LEN]; - int cforms = 0, // current loaded forms - ci = 0, // cursor index - ch = 0, // input key - i; - int tid = 0; - char uid[IDLEN+1]; - FILE *fpregq = regq_init_pull(); - - if (!fpregq) - return 0; - - while (ch != 'q') - { - // initialize and prepare - memset(ans, 0, sizeof(ans)); - memset(rejects, 0, sizeof(rejects)); - memset(forms, 0, sizeof(forms)); - memset(lfds, 0, sizeof(lfds)); - cforms = 0; - clear(); - - // load forms - while (cforms < FORMS_IN_PAGE) - { - if (!regq_pull(fpregq, uid)) - break; - i = cforms; // align index - - // check if user exists. - memset(&muser, 0, sizeof(muser)); - unum = getuser(uid, &muser); - if (unum < 1) - { - regq_delete(uid); - continue; - } - - // check if regform exists. - if (!regfrm_exist(uid)) - { - // TODO delete here? - regq_delete(uid); - continue; - } - // try to lock - lfds[i] = regfrm_trylock(uid); - if (lfds[i] <= 0) - continue; - - // load it - if (!regfrm_load(uid, &forms[i])) - { - regfrm_delete(uid); - regfrm_unlock(lfds[i]); - // regq_delete(uid); // done in regfrm_delete - continue; - } - - forms[i].exist = 1; - forms[i].online = search_ulist(unum) ? 1 : 0; - - // assign default answers - if (muser.userlevel & PERM_LOGINOK) - ans[i] = 'd'; -#ifdef REGFORM_DISABLE_ONLINE_USER - else if (forms[i].online) - ans[i] = 's'; -#endif // REGFORM_DISABLE_ONLINE_USER - - - // display - move(i*2, 0); - prints(" %2d%s %s%-12s " ANSI_RESET, - i+1, - (unum == 0) ? ANSI_COLOR(1;31) "D" : - ( (muser.userlevel & PERM_LOGINOK) ? - ANSI_COLOR(1;33) "Y" : -#ifdef REGFORM_DISABLE_ONLINE_USER - forms[i].online ? "s" : -#endif - "."), - forms[i].online ? ANSI_COLOR(1;35) : ANSI_COLOR(1), - forms[i].userid); - - prints( ANSI_COLOR(1;31) "%19s " - ANSI_COLOR(1;32) "%-40s" ANSI_RESET"\n", - forms[i].name, forms[i].career); - - move(i*2+1, 0); - prints(" %s %-50s%20s\n", - (muser.userlevel & PERM_NOREGCODE) ? - ANSI_COLOR(1;31) "T" ANSI_RESET : " ", - forms[i].addr, forms[i].phone); - - cforms++, tid ++; - } - - // if no more forms then leave. - if (cforms < 1) - break; - - // adjust cursor if required - if (ci >= cforms) - ci = cforms-1; - - // display page info - { - char msg[STRLEN]; - snprintf(msg, sizeof(msg), - "%s ¤wÅã¥Ü %d ¥÷µù¥U³æ ", // "(%2d%%) ", - dryrun? "(´ú¸Õ¼Ò¦¡)" : "", - tid); - prints(ANSI_COLOR(7) "\n%78s" ANSI_RESET "\n", msg); - } - - // handle user input - prompt_regform_ui(); - ch = 0; - while (ch != 'q' && ch != ' ') { - ch = cursor_key(ci*2, 0); - switch (ch) - { - // nav keys - case KEY_UP: - case 'k': - if (ci > 0) ci--; - break; - - case KEY_DOWN: - case 'j': - ch = 'j'; // go next - break; - - // quick nav (assuming to FORMS_IN_PAGE=10) - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - ci = ch - '1'; - if (ci >= cforms) ci = cforms-1; - break; - case '0': - ci = 10-1; - if (ci >= cforms) ci = cforms-1; - break; - - /* - case KEY_HOME: ci = 0; break; - case KEY_END: ci = cforms-1; break; - */ - - // abort - case KEY_END: - case 'q': - ch = 'q'; - if (getans("½T©wnÂ÷¶}¤F¶Ü¡H (¥»¶Åܧó±N¤£·|Àx¦s) [y/N]: ") != 'y') - { - prompt_regform_ui(); - ch = 0; - continue; - } - break; - - // prepare to go next page - case KEY_PGDN: - case ' ': - ch = ' '; - - { - int blanks = 0; - // solving blank (undecided entries) - for (i = 0, blanks = 0; i < cforms; i++) - if (ans[i] == 0) blanks ++; - - if (!blanks) - break; - - // have more blanks - ch = getans("©|¥¼«ü©wªº %d Ó¶µ¥Øn: (S¸õ¹L/y³q¹L/n©Úµ´/eÄ~Äò½s¿è): ", - blanks); - } - - if (ch == 'e') - { - prompt_regform_ui(); - ch = 0; - continue; - } - if (ch == 'y') { - // do nothing. - } else if (ch == 'n') { - // query reject reason - resolve_reason(rsn, yMsg); - if (*rsn == 0) - ch = 's'; - } else ch = 's'; - - // filling answers - for (i = 0; i < cforms; i++) - { - if (ans[i] != 0) - continue; - ans[i] = ch; - if (ch != 'n') - continue; - strlcpy(rejects[i], rsn, REASON_LEN); - } - - ch = ' '; // go to page mode! - break; - - // function keys - case 'y': // accept -#ifdef REGFORM_DISABLE_ONLINE_USER - if (forms[ci].online) - { - vmsg("¼È¤£¶}©ñ¼f®Ö¦b½u¤W¨Ï¥ÎªÌ¡C"); - break; - } -#endif - case 's': // skip - case 'd': // delete - case KEY_DEL: //delete - if (ch == KEY_DEL) ch = 'd'; - - grayout(ci*2, ci*2+1, GRAYOUT_DARK); - move_ansi(ci*2, 4); outc(ch); - ans[ci] = ch; - ch = 'j'; // go next - break; - - case 'u': // undo -#ifdef REGFORM_DISABLE_ONLINE_USER - if (forms[ci].online) - { - vmsg("¼È¤£¶}©ñ¼f®Ö¦b½u¤W¨Ï¥ÎªÌ¡C"); - break; - } -#endif - grayout(ci*2, ci*2+1, GRAYOUT_NORM); - move_ansi(ci*2, 4); outc('.'); - ans[ci] = 0; - ch = 'j'; // go next - break; - - case 'n': // reject -#ifdef REGFORM_DISABLE_ONLINE_USER - if (forms[ci].online) - { - vmsg("¼È¤£¶}©ñ¼f®Ö¦b½u¤W¨Ï¥ÎªÌ¡C"); - break; - } -#endif - // query for reason - resolve_reason(rejects[ci], yMsg); - prompt_regform_ui(); - - if (!rejects[ci][0]) - break; - - move(yMsg, 0); - prints("°h¦^ %s µù¥U³æì¦]:\n %s\n", forms[ci].userid, rejects[ci]); - - // do reject - grayout(ci*2, ci*2+1, GRAYOUT_DARK); - move_ansi(ci*2, 4); outc(ch); - ans[ci] = ch; - ch = 'j'; // go next - - break; - } // switch(ch) - - // change cursor - if (ch == 'j' && ++ci >= cforms) - ci = cforms -1; - } // while(ch != QUIT/SAVE) - - // if exit, we still need to skip all read forms - if (ch == 'q') - { - for (i = 0; i < cforms; i++) - ans[i] = 's'; - } - - // page complete (save). - assert(ch == ' ' || ch == 'q'); - - // save/commit if required. - if (dryrun) - { - // prmopt for debug - clear(); - stand_title("´ú¸Õ¼Ò¦¡"); - outs("±z¥¿¦b°õ¦æ´ú¸Õ¼Ò¦¡¡A©Ò¥Hè¼fªºµù¥U³æ¨Ã¤£·|¥Í®Ä¡C\n" - "¤U±¦C¥Xªº¬Oè¤~±z¼f§¹ªºµ²ªG:\n\n"); - - for (i = 0; i < cforms; i++) - { - char justify[REGLEN]; - if (ans[i] == 'y') - snprintf(justify, sizeof(justify), // build justify string - "%s:%s:%s", forms[i].phone, forms[i].career, cuser.userid); - - prints("%2d. %-12s - %c %s\n", i+1, forms[i].userid, ans[i], - ans[i] == 'n' ? rejects[i] : - ans[i] == 'y' ? justify : ""); - } - if (ch != 'q') - pressanykey(); - } - else - { - // real functionality - for (i = 0; i < cforms; i++) - { - switch(ans[i]) - { - case 'a': // accept - regfrm_accept(&forms[i]); - break; - - case 'd': // delete - regfrm_delete(uid); - break; - - case 'n': // reject - regfrm_reject(&forms[i], rsn); - break; - - case 's': // skip - // do nothing. - break; - - default: - assert(0); - break; - } - } - } // !dryrun - - // unlock all forms - for (i = 0; i < cforms; i++) - regfrm_unlock(lfds[i]); - - } // while (ch != 'q') - - regq_end_pull(fpregq); - - // finishing - clear(); move(5, 0); - prints("±z¼f¤F %d ¥÷µù¥U³æ¥÷¡C", tid); - pressanykey(); - return 0; -} - -///////////////////////////////////////////////////////////////////////////// -// Regform UI -// ³B²z Register Form -///////////////////////////////////////////////////////////////////////////// - -/* Auto-Regform-Scan - * FIXME ¯u¬O¤@¹Î©U§£ - * - * fdata ¥Î¤F¤Ó¦h magic number - * return value À³¸Ó¬O«ü reason (return index + 1) - * ans[0] «üªº¬O±bºÞ¿ï¾Üªº¡u¿ù»~ªºÄæ¦ì¡v (Register ¿ï³æ¸Ì¬Ý¨ìªº¨º¨Ç) - */ -static int -auto_scan(char fdata[][STRLEN], char ans[]) -{ - int good = 0; - int count = 0; - int i; - char temp[10]; - - if (!strncmp(fdata[1], "¤p", 2) || strstr(fdata[1], "¤X") - || strstr(fdata[1], "½Ö") || strstr(fdata[1], "¤£")) { - ans[0] = '0'; - return 1; - } - strlcpy(temp, fdata[1], 3); - - /* Å|¦r */ - if (!strncmp(temp, &(fdata[1][2]), 2)) { - ans[0] = '0'; - return 1; - } - if (strlen(fdata[1]) >= 6) { - if (strstr(fdata[1], "³¯¤ô«ó")) { - ans[0] = '0'; - return 1; - } - if (strstr("»¯¿ú®]§õ©P§d¾G¤ý", temp)) - good++; - else if (strstr("§ùÃC¶ÀªL³¯©x§E¨¯¼B", temp)) - good++; - else if (strstr("Ĭ¤è§d§f§õªò±i¹ùÀ³Ä¬", temp)) - good++; - else if (strstr("®}ÁÂ¥Û¿c¬IÀ¹¯Îð", temp)) - good++; - } - if (!good) - return 0; - - if (!strcmp(fdata[2], fdata[3]) || - !strcmp(fdata[2], fdata[4]) || - !strcmp(fdata[3], fdata[4])) { - ans[0] = '4'; - return 5; - } - if (strstr(fdata[2], "¤j")) { - if (strstr(fdata[2], "¥x") || strstr(fdata[2], "²H") || - strstr(fdata[2], "¥æ") || strstr(fdata[2], "¬F") || - strstr(fdata[2], "²M") || strstr(fdata[2], "ĵ") || - strstr(fdata[2], "®v") || strstr(fdata[2], "»Ê¶Ç") || - strstr(fdata[2], "¤¤¥¡") || strstr(fdata[2], "¦¨") || - strstr(fdata[2], "»²") || strstr(fdata[2], "ªF§d")) - good++; - } else if (strstr(fdata[2], "¤k¤¤")) - good++; - - if (strstr(fdata[3], "¦a²y") || strstr(fdata[3], "¦t©z") || - strstr(fdata[3], "«H½c")) { - ans[0] = '2'; - return 3; - } - if (strstr(fdata[3], "¥«") || strstr(fdata[3], "¿¤")) { - if (strstr(fdata[3], "¸ô") || strstr(fdata[3], "µó")) { - if (strstr(fdata[3], "¸¹")) - good++; - } - } - for (i = 0; fdata[4][i]; i++) { - if (isdigit((int)fdata[4][i])) - count++; - } - - if (count <= 4) { - ans[0] = '3'; - return 4; - } else if (count >= 7) - good++; - - if (good >= 3) { - ans[0] = 'y'; - return -1; - } else - return 0; -} - -///////////////////////////////////////////////////////////////////////////// -// Traditional Regform UI -///////////////////////////////////////////////////////////////////////////// -// TODO XXX process someone directly, according to target_uid. -int -scan_register_form(const char *regfile, int automode, const char *target_uid) -{ - char genbuf[200]; - char *field[] = { - "uid", "name", "career", "addr", "phone", "email", NULL - }; - char *finfo[] = { - "±b¸¹", "¯u¹ê©m¦W", "ªA°È³æ¦ì", "¥Ø«e¦í§}", - "³sµ¸¹q¸Ü", "¹q¤l¶l¥ó«H½c", NULL - }; - char *reason[REJECT_REASONS+1] = { - "¿é¤J¯u¹ê©m¦W", - "¸Ô¶ñ¡u(²¦·~)¾Ç®Õ¤Î¡y¨t¡z¡y¯Å¡z¡v©Î¡uªA°È³æ¦ì(§t©ÒÄÝ¿¤¥«¤Î¾ºÙ)¡v", - "¶ñ¼g§¹¾ãªº¦í§}¸ê®Æ (§t¿¤¥«¦WºÙ, ¥x¥_¥«½Ð§t¦æ¬F°Ï°ì¡^", - "¸Ô¶ñ³sµ¸¹q¸Ü (§t°Ï°ì½X, ¤¤¶¡¤£¥Î¥[ '-', '(', ')'µ¥²Å¸¹", - "ºë½T¨Ã§¹¾ã¶ñ¼gµù¥U¥Ó½Ðªí", - "¥Î¤¤¤å¶ñ¼g¥Ó½Ð³æ", - NULL - }; - char *autoid = "AutoScan"; - userec_t muser; - FILE *fn, *fout, *freg; - char fdata[6][STRLEN]; - char fname[STRLEN] = "", buf[STRLEN]; - char ans[4], *ptr, *uid; - int n = 0, unum = 0, tid = 0; - int nSelf = 0, nAuto = 0; - - uid = cuser.userid; - move(2, 0); - - fn = pull_regform(regfile, fname, -1); - if (!fn) - return -1; - - while( fgets(genbuf, STRLEN, fn) ){ - memset(fdata, 0, sizeof(fdata)); - do { - if( genbuf[0] == '-' ) - break; - if ((ptr = (char *)strstr(genbuf, ": "))) { - *ptr = '\0'; - for (n = 0; field[n]; n++) { - if (strcmp(genbuf, field[n]) == 0) { - strlcpy(fdata[n], ptr + 2, sizeof(fdata[n])); - if ((ptr = (char *)strchr(fdata[n], '\n'))) - *ptr = '\0'; - } - } - } - } while( fgets(genbuf, STRLEN, fn) ); - tid ++; - - if ((unum = getuser(fdata[0], &muser)) == 0) { - move(2, 0); - clrtobot(); - outs("¨t²Î¿ù»~¡A¬dµL¦¹¤H\n\n"); - for (n = 0; field[n]; n++) - prints("%s : %s\n", finfo[n], fdata[n]); - pressanykey(); - } else { - if (automode) - uid = autoid; - - if ((!automode || !auto_scan(fdata, ans))) { - uid = cuser.userid; - - move(1, 0); - clrtobot(); - prints("±b¸¹¦ì¸m : %d\n", unum); - user_display(&muser, 1); - move(14, 0); - prints(ANSI_COLOR(1;32) "------------- " - "½Ð¯¸ªøÄY®æ¼f®Ö¨Ï¥ÎªÌ¸ê®Æ¡A³o¬O²Ä %d ¥÷" - "------------" ANSI_RESET "\n", tid); - prints(" %-12s: %s\n", finfo[0], fdata[0]); -#ifdef FOREIGN_REG - prints("0.%-12s: %s%s\n", finfo[1], fdata[1], - muser.uflag2 & FOREIGN ? " (¥~Äy)" : ""); -#else - prints("0.%-12s: %s\n", finfo[1], fdata[1]); -#endif - for (n = 2; field[n]; n++) { - prints("%d.%-12s: %s\n", n - 1, finfo[n], fdata[n]); - } - if (muser.userlevel & PERM_LOGINOK) { - ans[0] = getkey("¦¹±b¸¹¤w¸g§¹¦¨µù¥U, " - "§ó·s(Y/N/Skip)¡H[N] "); - if (ans[0] != 'y' && ans[0] != 's') - ans[0] = 'd'; - } else { - if (search_ulist(unum) == NULL) - { - move(b_lines, 0); clrtoeol(); - outs("¬O§_±µ¨ü¦¹¸ê®Æ(Y/N/Q/Del/Skip)¡H[S] "); - // FIXME if the user got online here - ans[0] = igetch(); - } - else - ans[0] = 's'; - ans[0] = tolower(ans[0]); - if (ans[0] != 'y' && ans[0] != 'n' && - ans[0] != 'q' && ans[0] != 'd' && - !('0' <= ans[0] && ans[0] < ('0' + REJECT_REASONS))) - ans[0] = 's'; - ans[1] = 0; - } - nSelf++; - } else - nAuto++; - - switch (ans[0]) { - case 'q': - if ((freg = fopen(regfile, "a"))) { - for (n = 0; field[n]; n++) - fprintf(freg, "%s: %s\n", field[n], fdata[n]); - fprintf(freg, "----\n"); - while (fgets(genbuf, STRLEN, fn)) - fputs(genbuf, freg); - fclose(freg); - } - case 'd': - break; - - case '0': case '1': case '2': - case '3': case '4': case '5': - /* please confirm match REJECT_REASONS here */ - case 'n': - if (ans[0] == 'n') { - int nf = 0; - move(8, 0); - clrtobot(); - outs("½Ð´£¥X°h¦^¥Ó½Ðªíì¦]¡A«ö <enter> ¨ú®ø\n"); - for (n = 0; n < REJECT_REASONS; n++) - prints("%d) ½Ð%s\n", n, reason[n]); - outs("\n"); // preserved for prompt - for (nf = 0; field[nf]; nf++) - prints("%s: %s\n", finfo[nf], fdata[nf]); - } else - buf[0] = ans[0]; - - if (ans[0] != 'n' || - getdata(9 + n, 0, "°h¦^ì¦]: ", buf, 60, DOECHO)) - if ((buf[0] - '0') >= 0 && (buf[0] - '0') < n) { - int i; - fileheader_t mhdr; - char title[128], buf1[80]; - FILE *fp; - - sethomepath(buf1, muser.userid); - stampfile(buf1, &mhdr); - strlcpy(mhdr.owner, cuser.userid, sizeof(mhdr.owner)); - strlcpy(mhdr.title, "[µù¥U¥¢±Ñ]", TTLEN); - mhdr.filemode = 0; - sethomedir(title, muser.userid); - if (append_record(title, &mhdr, sizeof(mhdr)) != -1) { - char rejfn[PATHLEN]; - fp = fopen(buf1, "w"); - - for(i = 0; buf[i] && i < sizeof(buf); i++){ - if (buf[i] >= '0' && buf[i] < '0'+n) - { - fprintf(fp, "[°h¦^ì¦]] ½Ð%s\n", - reason[buf[i] - '0']); - } - } - - fclose(fp); - - // build reject file - sethomefile(rejfn, muser.userid, FN_REJECT_NOTIFY); - Copy(buf1, rejfn); - } - if ((fout = fopen(FN_REGISTER_LOG, "a"))) { - for (n = 0; field[n]; n++) - fprintf(fout, "%s: %s\n", field[n], fdata[n]); - fprintf(fout, "Date: %s\n", Cdate(&now)); - fprintf(fout, "Rejected: %s [%s]\n----\n", - uid, buf); - fclose(fout); - } - break; - } - move(10, 0); - clrtobot(); - outs("¨ú®ø°h¦^¦¹µù¥U¥Ó½Ðªí"); - /* no break? */ - - case 's': - if ((freg = fopen(regfile, "a"))) { - for (n = 0; field[n]; n++) - fprintf(freg, "%s: %s\n", field[n], fdata[n]); - fprintf(freg, "----\n"); - fclose(freg); - } - break; - - default: - outs("¥H¤U¨Ï¥ÎªÌ¸ê®Æ¤w¸g§ó·s:\n"); - mail_muser(muser, "[µù¥U¦¨¥\\Åo]", "etc/registered"); - -#if FOREIGN_REG_DAY > 0 - if(muser.uflag2 & FOREIGN) - mail_muser(muser, "[¥X¤J¹ÒºÞ²z§½]", "etc/foreign_welcome"); -#endif - - muser.userlevel |= (PERM_LOGINOK | PERM_POST); - strlcpy(muser.realname, fdata[1], sizeof(muser.realname)); - strlcpy(muser.address, fdata[3], sizeof(muser.address)); - strlcpy(muser.email, fdata[5], sizeof(muser.email)); - snprintf(genbuf, sizeof(genbuf), "%s:%s:%s", - fdata[4], fdata[2], uid); - strlcpy(muser.justify, genbuf, sizeof(muser.justify)); - - passwd_update(unum, &muser); - // XXX TODO notify users? - sendalert(muser.userid, ALERT_PWD_PERM); // force to reload perm - - sethomefile(buf, muser.userid, FN_JUSTIFY); - log_file(buf, LOG_CREAT, genbuf); - - if ((fout = fopen(FN_REGISTER_LOG, "a"))) { - for (n = 0; field[n]; n++) - fprintf(fout, "%s: %s\n", field[n], fdata[n]); - fprintf(fout, "Date: %s\n", Cdate(&now)); - fprintf(fout, "Approved: %s\n", uid); - fprintf(fout, "----\n"); - fclose(fout); - } - sethomefile(genbuf, muser.userid, FN_JUSTIFY_WAIT); - unlink(genbuf); - break; - } - } - } - - fclose(fn); - unlink(fname); - - clear(); move(5, 0); - prints("±z¼f¤F %d ¥÷µù¥U³æ¡AAutoScan ¼f¤F %d ¥÷", nSelf, nAuto); - pressanykey(); - return (0); -} - -///////////////////////////////////////////////////////////////////////////// -// New Regform UI -///////////////////////////////////////////////////////////////////////////// - -// #define REGFORM_DISABLE_ONLINE_USER -// #define FORMS_IN_PAGE (10) - -int -handle_register_form(const char *regfile, int dryrun) -{ - int unum = 0; - int yMsg = FORMS_IN_PAGE*2+1; - FILE *fp = NULL; - userec_t muser; - RegformEntry forms [FORMS_IN_PAGE]; - char ans [FORMS_IN_PAGE]; - char rejects[FORMS_IN_PAGE][REASON_LEN]; // reject reason length - char fname [PATHLEN] = ""; - char justify[REGLEN+1]; - char rsn [REASON_LEN]; - int cforms = 0, // current loaded forms - parsed = 0, // total parsed forms - ci = 0, // cursor index - ch = 0, // input key - i, blanks; - long fsz = 0, fpos = 0; - - // prepare reg tickets - if (dryrun) - { - // directly open regfile to try - fp = fopen(regfile, "rt"); - } else { - fp = pull_regform(regfile, fname, -1); - } - - if (!fp) - return 0; - - // retreieve file info - fpos = ftell(fp); - fseek(fp, 0, SEEK_END); - fsz = ftell(fp); - fseek(fp, fpos, SEEK_SET); - if (!fsz) fsz = 1; - - while (ch != 'q') - { - // initialize and prepare - memset(ans, 0, sizeof(ans)); - memset(rejects, 0, sizeof(rejects)); - memset(forms, 0, sizeof(forms)); - cforms = 0; - - // load forms - while (cforms < FORMS_IN_PAGE && load_regform_entry(&forms[cforms], fp)) - cforms++, parsed ++; - - // if no more forms then leave. - // TODO what if regform error? - if (cforms < 1) - break; - - // adjust cursor if required - if (ci >= cforms) - ci = cforms-1; - - // display them all. - clear(); - for (i = 0; i < cforms; i++) - { - // fetch user information - memset(&muser, 0, sizeof(muser)); - unum = getuser(forms[i].userid, &muser); - forms[i].exist = unum ? 1 : 0; - if (unum) forms[i].online = search_ulist(unum) ? 1 : 0; - - // if already got login level, delete by default. - if (!unum) - ans[i] = 'd'; - else { - if (muser.userlevel & PERM_LOGINOK) - ans[i] = 'd'; -#ifdef REGFORM_DISABLE_ONLINE_USER - else if (forms[i].online) - ans[i] = 's'; -#endif // REGFORM_DISABLE_ONLINE_USER - } - - // print - move(i*2, 0); - prints(" %2d%s %s%-12s " ANSI_RESET, - i+1, - (unum == 0) ? ANSI_COLOR(1;31) "D" : - ( (muser.userlevel & PERM_LOGINOK) ? - ANSI_COLOR(1;33) "Y" : -#ifdef REGFORM_DISABLE_ONLINE_USER - forms[i].online ? "s" : -#endif - "."), - forms[i].online ? ANSI_COLOR(1;35) : ANSI_COLOR(1), - forms[i].userid); - - prints( ANSI_COLOR(1;31) "%19s " - ANSI_COLOR(1;32) "%-40s" ANSI_RESET"\n", - forms[i].name, forms[i].career); - - move(i*2+1, 0); - prints(" %s %-50s%20s\n", - (muser.userlevel & PERM_NOREGCODE) ? - ANSI_COLOR(1;31) "T" ANSI_RESET : " ", - forms[i].addr, forms[i].phone); - } - - // display page info - { - char msg[STRLEN]; - fpos = ftell(fp); - if (fpos > fsz) fsz = fpos*10; - snprintf(msg, sizeof(msg), - "%s ¤wÅã¥Ü %d ¥÷µù¥U³æ (%2d%%) ", - dryrun? "(´ú¸Õ¼Ò¦¡)" : "", - parsed, (int)(fpos*100/fsz)); - prints(ANSI_COLOR(7) "\n%78s" ANSI_RESET "\n", msg); - } - - // handle user input - prompt_regform_ui(); - ch = 0; - while (ch != 'q' && ch != ' ') { - ch = cursor_key(ci*2, 0); - switch (ch) - { - // nav keys - case KEY_UP: - case 'k': - if (ci > 0) ci--; - break; - - case KEY_DOWN: - case 'j': - ch = 'j'; // go next - break; - - // quick nav (assuming to FORMS_IN_PAGE=10) - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - ci = ch - '1'; - if (ci >= cforms) ci = cforms-1; - break; - case '0': - ci = 10-1; - if (ci >= cforms) ci = cforms-1; - break; - - /* - case KEY_HOME: ci = 0; break; - case KEY_END: ci = cforms-1; break; - */ - - // abort - case KEY_END: - case 'q': - ch = 'q'; - if (getans("½T©wnÂ÷¶}¤F¶Ü¡H (¥»¶Åܧó±N¤£·|Àx¦s) [y/N]: ") != 'y') - { - prompt_regform_ui(); - ch = 0; - continue; - } - break; - - // prepare to go next page - case KEY_PGDN: - case ' ': - ch = ' '; - - // solving blank (undecided entries) - for (i = 0, blanks = 0; i < cforms; i++) - if (ans[i] == 0) blanks ++; - - if (!blanks) - break; - - // have more blanks - ch = getans("©|¥¼«ü©wªº %d Ó¶µ¥Øn: (S¸õ¹L/y³q¹L/n©Úµ´/eÄ~Äò½s¿è): ", - blanks); - - if (ch == 'e') - { - prompt_regform_ui(); - ch = 0; - continue; - } - if (ch == 'y') { - // do nothing. - } else if (ch == 'n') { - // query reject reason - resolve_reason(rsn, yMsg); - if (*rsn == 0) - ch = 's'; - } else ch = 's'; - - // filling answers - for (i = 0; i < cforms; i++) - { - if (ans[i] != 0) - continue; - ans[i] = ch; - if (ch != 'n') - continue; - strlcpy(rejects[i], rsn, REASON_LEN); - } - - ch = ' '; // go to page mode! - break; - - // function keys - case 'y': // accept -#ifdef REGFORM_DISABLE_ONLINE_USER - if (forms[ci].online) - { - vmsg("¼È¤£¶}©ñ¼f®Ö¦b½u¤W¨Ï¥ÎªÌ¡C"); - break; - } -#endif - case 's': // skip - case 'd': // delete - case KEY_DEL: //delete - if (ch == KEY_DEL) ch = 'd'; - - grayout(ci*2, ci*2+1, GRAYOUT_DARK); - move_ansi(ci*2, 4); outc(ch); - ans[ci] = ch; - ch = 'j'; // go next - break; - - case 'u': // undo -#ifdef REGFORM_DISABLE_ONLINE_USER - if (forms[ci].online) - { - vmsg("¼È¤£¶}©ñ¼f®Ö¦b½u¤W¨Ï¥ÎªÌ¡C"); - break; - } -#endif - grayout(ci*2, ci*2+1, GRAYOUT_NORM); - move_ansi(ci*2, 4); outc('.'); - ans[ci] = 0; - ch = 'j'; // go next - break; - - case 'n': // reject -#ifdef REGFORM_DISABLE_ONLINE_USER - if (forms[ci].online) - { - vmsg("¼È¤£¶}©ñ¼f®Ö¦b½u¤W¨Ï¥ÎªÌ¡C"); - break; - } -#endif - // query for reason - resolve_reason(rejects[ci], yMsg); - prompt_regform_ui(); - - if (!rejects[ci][0]) - break; - - move(yMsg, 0); - prints("°h¦^ %s µù¥U³æì¦]:\n %s\n", forms[ci].userid, rejects[ci]); - - // do reject - grayout(ci*2, ci*2+1, GRAYOUT_DARK); - move_ansi(ci*2, 4); outc(ch); - ans[ci] = ch; - ch = 'j'; // go next - - break; - } // switch(ch) - - // change cursor - if (ch == 'j' && ++ci >= cforms) - ci = cforms -1; - } // while(ch != QUIT/SAVE) - - // if exit, we still need to skip all read forms - if (ch == 'q') - { - for (i = 0; i < cforms; i++) - ans[i] = 's'; - } - - // page complete (save). - assert(ch == ' ' || ch == 'q'); - - // save/commit if required. - if (dryrun) - { - // prmopt for debug - clear(); - stand_title("´ú¸Õ¼Ò¦¡"); - outs("±z¥¿¦b°õ¦æ´ú¸Õ¼Ò¦¡¡A©Ò¥Hè¼fªºµù¥U³æ¨Ã¤£·|¥Í®Ä¡C\n" - "¤U±¦C¥Xªº¬Oè¤~±z¼f§¹ªºµ²ªG:\n\n"); - - for (i = 0; i < cforms; i++) - { - if (ans[i] == 'y') - snprintf(justify, sizeof(justify), // build justify string - "%s:%s:%s", forms[i].phone, forms[i].career, cuser.userid); - - prints("%2d. %-12s - %c %s\n", i+1, forms[i].userid, ans[i], - ans[i] == 'n' ? rejects[i] : - ans[i] == 'y' ? justify : ""); - } - if (ch != 'q') - pressanykey(); - } - else - { - // real functionality - for (i = 0; i < cforms; i++) - { - if (ans[i] == 'y') - { - // build justify string - snprintf(justify, sizeof(justify), - "%s:%s:%s", forms[i].phone, forms[i].career, cuser.userid); - - regform_accept(forms[i].userid, justify); - // log form to FN_REGISTER_LOG - append_regform(&forms[i], FN_REGISTER_LOG, - "Approved", cuser.userid, NULL); - } - else if (ans[i] == 'n') - { - regform_reject(forms[i].userid, rejects[i]); - // log form to FN_REGISTER_LOG - append_regform(&forms[i], FN_REGISTER_LOG, - "Rejected", cuser.userid, rejects[i]); - } - else if (ans[i] == 's') - { - // append form back to fn_register - append_regform(&forms[i], fn_register, - NULL, NULL, NULL); - } - } - } // !dryrun - - } // while (ch != 'q') - - // cleaning left regforms - if (!dryrun) - { - pump_regform(regfile, fp); - fclose(fp); - unlink(fname); - } else { - // directly close file should be OK. - fclose(fp); - } - - return 0; -} - -int -m_register(void) -{ - FILE *fn; - int x, y, wid, len; - char ans[4]; - char genbuf[200]; - - if ((fn = fopen(fn_register, "r")) == NULL) { - outs("¥Ø«e¨ÃµL·sµù¥U¸ê®Æ"); - return XEASY; - } - stand_title("¼f®Ö¨Ï¥ÎªÌµù¥U¸ê®Æ"); - y = 2; - x = wid = 0; - - while (fgets(genbuf, STRLEN, fn) && x < 65) { - if (strncmp(genbuf, "uid: ", 5) == 0) { - move(y++, x); - outs(genbuf + 5); - len = strlen(genbuf + 5); - if (len > wid) - wid = len; - if (y >= t_lines - 3) { - y = 2; - x += wid + 2; - } - } - } - fclose(fn); - getdata(b_lines - 1, 0, - "¶}©l¼f®Ö¶Ü(Auto¦Û°Ê/Yes¤â°Ê/No¤£¼f/Exp·s¬É±)¡H[N] ", - ans, sizeof(ans), LCECHO); - if (ans[0] == 'a') - scan_register_form(fn_register, 1, NULL); - else if (ans[0] == 'y') - scan_register_form(fn_register, 0, NULL); - else if (ans[0] == 'e') - { -#ifdef EXP_ADMIN_REGFORM_DRYRUN - int dryrun = 0; - if (getans("§An¶i¦æ¯Â´ú¸Õ(T)ÁÙ¬O¯uªº°õ¦æ¼f®Ö(y)¡H") == 'y') - { - vmsg("¶i¤J¹ê»Ú°õ¦æ¼Ò¦¡¡A©Ò¦³¼f®Ö°Ê§@³£¬O¯uªº¡C"); - dryrun = 0; - } else { - vmsg("´ú¸Õ¼Ò¦¡¡C"); - dryrun = 1; - } - handle_register_form(fn_register, dryrun); -#else - // run directly. - handle_register_form(fn_register, 0); -#endif - } - - return 0; -} - -int -cat_register(void) -{ - if (system("cat register.new.tmp >> register.new") == 0 && - unlink("register.new.tmp") == 0) - vmsg("OK ÂP~~ Ä~Äò¥h¾Ä°«§a!!"); - else - vmsg("¨S¿ìªkCAT¹L¥h©O ¥hÀˬd¤@¤U¨t²Î§a!!"); - return 0; -} - -/* vim:sw=4 - */ diff --git a/mbbsd/reversi.c b/mbbsd/reversi.c deleted file mode 100644 index ea64f35a..00000000 --- a/mbbsd/reversi.c +++ /dev/null @@ -1,513 +0,0 @@ -/* $Id$ */ - -#include "bbs.h" - -#define MAX_TIME (300) -#define BRDSIZ (8) /* ´Ñ½L³æÃä¤j¤p */ - -#define NONE_CHESS " " -#define WHITE_CHESS "¡´" -#define BLACK_CHESS "¡³" -#define HINT_CHESS "¡" -#define NONE 0 -#define HINT 1 -#define BLACK 2 -#define WHITE 3 - -#define STARTY 10 - -#define INVERT(COLOR) (((COLOR))==WHITE?BLACK:WHITE) - -#define IS_BLANK(COLOR) ((COLOR) < BLACK) /* NONE or HINT */ -#define IS_CHESS(COLOR) ((COLOR) >= BLACK) -#define TURN_TO_COLOR(TURN) (WHITE - (TURN)) -#define COLOR_TO_TURN(COLOR) (WHITE - (COLOR)) - -typedef char color_t; -typedef color_t board_t[BRDSIZ + 2][BRDSIZ + 2]; -typedef color_t (*board_p)[BRDSIZ + 2]; -/* [0] & [9] are dummy */ - -typedef struct { - ChessStepType type; /* necessary one */ - color_t color; - rc_t loc; -} reversi_step_t; - -typedef struct { - int number[2]; -} reversi_tag_t; - -/* chess framework action functions */ -static void reversi_init_user(const userinfo_t *uinfo, ChessUser *user); -static void reversi_init_user_userec(const userec_t *urec, ChessUser *user); -static void reversi_init_board(board_t board); -static void reversi_drawline(const ChessInfo* info, int line); -static void reversi_movecur(int r, int c); -static int reversi_prepare_play(ChessInfo* info); -static int reversi_select(ChessInfo* info, rc_t scrloc, ChessGameResult* result); -static void reversi_prepare_step(ChessInfo* info, const reversi_step_t* step); -static ChessGameResult reversi_apply_step(board_t board, const reversi_step_t* step); -static void reversi_drawstep(ChessInfo* info, const void* move); -static ChessGameResult reversi_post_game(ChessInfo* info); -static void reversi_gameend(ChessInfo* info, ChessGameResult result); -static void reversi_genlog(ChessInfo* info, FILE* fp, ChessGameResult result); - -static const char *CHESS_TYPE[] = {NONE_CHESS, HINT_CHESS, BLACK_CHESS, WHITE_CHESS}; -static const char DIRX[] = {-1, -1, -1, 0, 1, 1, 1, 0}; -static const char DIRY[] = {-1, 0, 1, 1, 1, 0, -1, -1}; - -static const ChessActions reversi_actions = { - &reversi_init_user, - &reversi_init_user_userec, - (void (*) (void*)) &reversi_init_board, - &reversi_drawline, - &reversi_movecur, - &reversi_prepare_play, - NULL, /* process_key */ - &reversi_select, - (void (*)(ChessInfo*, const void*)) &reversi_prepare_step, - (ChessGameResult (*)(void*, const void*)) &reversi_apply_step, - &reversi_drawstep, - &reversi_post_game, - &reversi_gameend, - &reversi_genlog -}; - -const static ChessConstants reversi_constants = { - sizeof(reversi_step_t), - MAX_TIME, - BRDSIZ, - BRDSIZ, - 0, - "¶Â¥Õ´Ñ", - "photo_reversi", -#ifdef GLOBAL_REVERSI_LOG - GLOBAL_REVERSI_LOG, -#else - NULL, -#endif - { "", "" }, - { "¥Õ´Ñ", "¶Â´Ñ" }, -}; - -static int -can_put(board_t board, color_t who, int x, int y) -{ - int i, temp, checkx, checky; - - if (IS_BLANK(board[x][y])) - for (i = 0; i < 8; ++i) { - checkx = x + DIRX[i]; - checky = y + DIRY[i]; - temp = board[checkx][checky]; - if (IS_BLANK(temp)) - continue; - if (temp != who) { - while (board[checkx += DIRX[i]][checky += DIRY[i]] == temp); - if (board[checkx][checky] == who) - return 1; - } - } - return 0; -} - -static int -caculate_hint(board_t board, color_t who) -{ - int i, j, count = 0; - - for (i = 1; i <= 8; i++) - for (j = 1; j <= 8; j++) { - if (board[i][j] == HINT) - board[i][j] = NONE; - if (can_put(board, who, i, j)) { - board[i][j] = HINT; - ++count; - } - } - return count; -} - -static void -reversi_init_user(const userinfo_t* uinfo, ChessUser* user) -{ - strlcpy(user->userid, uinfo->userid, sizeof(user->userid)); - user->win = - user->lose = - user->tie = 0; -} - -static void -reversi_init_user_userec(const userec_t* urec, ChessUser* user) -{ - strlcpy(user->userid, urec->userid, sizeof(user->userid)); - user->win = - user->lose = - user->tie = 0; -} - -static void -reversi_init_board(board_t board) -{ - memset(board, NONE, sizeof(board_t)); - board[4][4] = board[5][5] = WHITE; - board[4][5] = board[5][4] = BLACK; - - caculate_hint(board, BLACK); -} - -static void -reversi_drawline(const ChessInfo* info, int line){ - static const char* num_str[] = - {"", "¢°", "¢±", "¢²", "¢³", "¢´", "¢µ", "¢¶", "¢·"}; - if(line) - move(line, STARTY); - - if (line == 0) { - prints(ANSI_COLOR(1;46) " ¶Â¥Õ´Ñ¹ï¾Ô " ANSI_COLOR(45) - "%30s VS %-20s%10s" ANSI_RESET, - info->user1.userid, info->user2.userid, - info->mode == CHESS_MODE_WATCH ? "[Æ[´Ñ¼Ò¦¡]" : ""); - } else if (line == 2) - outs(" ¢Ï ¢Ð ¢Ñ ¢Ò ¢Ó ¢Ô ¢Õ ¢Ö"); - else if (line == 3) - outs("¢z¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢s¢w¢{"); - else if (line == 19) - outs("¢|¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢r¢w¢}"); - else if (line == 20) - prints(" (" BLACK_CHESS ") %-15s%2d%*s", - info->myturn ? info->user1.userid : info->user2.userid, - ((reversi_tag_t*)info->tag)->number[COLOR_TO_TURN(BLACK)], - 34 - 24, ""); - else if (line == 21) - prints(" (" WHITE_CHESS ") %-15s%2d%*s", - info->myturn ? info->user2.userid : info->user1.userid, - ((reversi_tag_t*)info->tag)->number[COLOR_TO_TURN(WHITE)], - 34 - 24, ""); - else if (line > 3 && line < 19) { - if ((line & 1) == 1) - outs("¢u¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢q¢w¢t"); - else { - int x = line / 2 - 1; - int y; - board_p board = (board_p) info->board; - - move(line, STARTY - 2); - prints("%s¢x", num_str[x]); - for(y = 1; y <= 8; ++y) - prints("%s¢x", CHESS_TYPE[(int) board[x][y]]); - } - } - - ChessDrawExtraInfo(info, line, 4); -} - -static void -reversi_movecur(int r, int c) -{ - move(r * 2 + 4, c * 4 + STARTY + 2); -} - -static int -reversi_prepare_play(ChessInfo* info) -{ - int x, y; - int result; - board_p board = (board_p) info->board; - reversi_tag_t* tag = (reversi_tag_t*) info->tag; - - tag->number[0] = tag->number[1] = 0; - for(x = 1; x <= 8; ++x) - for(y = 1; y <= 8; ++y) - if (IS_CHESS(board[x][y])) - ++tag->number[COLOR_TO_TURN(board[x][y])]; - - result = !caculate_hint(board, TURN_TO_COLOR(info->turn)); - if (result) { - reversi_step_t step = { CHESS_STEP_SPECIAL, TURN_TO_COLOR(info->turn) }; - if (info->turn == info->myturn) { - ChessStepSend(info, &step); - ChessHistoryAppend(info, &step); - strcpy(info->last_movestr, "§A¥²¶·©ñ±ó³o¤@¨B!!"); - } else { - ChessStepReceive(info, &step); - strcpy(info->last_movestr, "¹ï¤è¥²¶·©ñ±ó³o¤@¨B!!"); - } - } - - ChessRedraw(info); - return result; -} - -static int -reversi_select(ChessInfo* info, rc_t loc, ChessGameResult* result) -{ - board_p board = (board_p) info->board; - - ++loc.r; ++loc.c; - if (can_put(board, TURN_TO_COLOR(info->turn), loc.r, loc.c)) { - reversi_step_t step = { CHESS_STEP_NORMAL, - TURN_TO_COLOR(info->turn), loc }; - reversi_apply_step(board, &step); - - snprintf(info->last_movestr, sizeof(info->last_movestr), - "%c%d", step.loc.c - 1 + 'A', step.loc.r); - - ChessStepSend(info, &step); - ChessHistoryAppend(info, &step); - - return 1; - } else - return 0; -} - -static ChessGameResult -reversi_apply_step(board_t board, const reversi_step_t* step) -{ - int i; - color_t opposite = INVERT(step->color); - - if (step->type != CHESS_STEP_NORMAL) - return CHESS_RESULT_CONTINUE; - - for (i = 0; i < 8; ++i) { - int x = step->loc.r; - int y = step->loc.c; - - while (board[x += DIRX[i]][y += DIRY[i]] == opposite); - - if (board[x][y] == step->color) { - x = step->loc.r; - y = step->loc.c; - - while (board[x += DIRX[i]][y += DIRY[i]] == opposite) - board[x][y] = step->color; - } - } - board[step->loc.r][step->loc.c] = step->color; - - return CHESS_RESULT_CONTINUE; -} - -static void -reversi_prepare_step(ChessInfo* info, const reversi_step_t* step) -{ - if (step->type == CHESS_STEP_NORMAL) - snprintf(info->last_movestr, sizeof(info->last_movestr), - "%c%d", step->loc.c - 1 + 'A', step->loc.r); - else if (step->color == TURN_TO_COLOR(info->myturn)) - strcpy(info->last_movestr, "§A¥²¶·©ñ±ó³o¤@¨B!!"); - else - strcpy(info->last_movestr, "¹ï¤è¥²¶·©ñ±ó³o¤@¨B!!"); -} - -static void -reversi_drawstep(ChessInfo* info, const void* move) -{ - ChessRedraw(info); -} - -static ChessGameResult -reversi_post_game(ChessInfo* info) -{ - int x, y; - board_p board = (board_p) info->board; - reversi_tag_t* tag = (reversi_tag_t*) info->tag; - - tag->number[0] = tag->number[1] = 0; - for(x = 1; x <= 8; ++x) - for(y = 1; y <= 8; ++y) - if (board[x][y] == HINT) - board[x][y] = NONE; - else if (IS_CHESS(board[x][y])) - ++tag->number[COLOR_TO_TURN(board[x][y])]; - - ChessRedraw(info); - - if (tag->number[0] == tag->number[1]) - return CHESS_RESULT_TIE; - else if (tag->number[(int) info->myturn] < tag->number[info->myturn ^ 1]) - return CHESS_RESULT_LOST; - else - return CHESS_RESULT_WIN; -} - -static void -reversi_gameend(ChessInfo* info, ChessGameResult result) -{ - /* nothing to do now - * TODO game record */ -} - -static void -reversi_genlog(ChessInfo* info, FILE* fp, ChessGameResult result) -{ - char buf[ANSILINELEN] = ""; - const int nStep = info->history.used; - int i, x, y; - - getyx(&y, &x); - for (i = 2; i <= 21; i++) - { - move(i, 0); - inansistr(buf, sizeof(buf)-1); - fprintf(fp, "%s\n", buf); - } - move(y, x); - - fprintf(fp, "\n"); - fprintf(fp, "«ö z ¥i¶i¤J¥´ÃмҦ¡\n"); - fprintf(fp, "\n"); - - fprintf(fp, "<reversilog>\nblack:%s\nwhite:%s\n", - info->myturn ? info->user1.userid : info->user2.userid, - info->myturn ? info->user2.userid : info->user1.userid); - - for (i = 0; i < nStep; ++i) { - const reversi_step_t* const step = - (const reversi_step_t*) ChessHistoryRetrieve(info, i); - if (step->type == CHESS_STEP_NORMAL) - fprintf(fp, "[%2d]%s ==> %c%-5d", i + 1, - CHESS_TYPE[(int) step->color], - 'A' + step->loc.c - 1, step->loc.r); - else - fprintf(fp, "[%2d]%s ==> pass ", i + 1, - CHESS_TYPE[(int) step->color]); - if (i % 2) - fputc('\n', fp); - } - - if (i % 2) - fputc('\n', fp); - fputs("</reversilog>\n", fp); -} - -static int -reversi_loadlog(FILE *fp, ChessInfo *info) -{ - char buf[256]; - -#define INVALID_ROW(R) ((R) <= 0 || (R) > 8) -#define INVALID_COL(C) ((C) <= 0 || (C) > 8) - while (fgets(buf, sizeof(buf), fp)) { - if (strcmp("</reversilog>\n", buf) == 0) - return 1; - else if (strncmp("black:", buf, 6) == 0 || - strncmp("white:", buf, 6) == 0) { - /* /(black|white):([a-zA-Z0-9]+)/; $2 */ - userec_t rec; - ChessUser *user = (buf[0] == 'b' ? &info->user1 : &info->user2); - - chomp(buf); - if (getuser(buf + 6, &rec)) - reversi_init_user_userec(&rec, user); - } else if (buf[0] == '[') { - /* "[ 1]¡´ ==> C4 [ 2]¡³ ==> C5" */ - reversi_step_t step = { CHESS_STEP_NORMAL }; - int c, r; - const char *p = buf; - int i; - - for(i=0; i<2; i++) { - p = strchr(p, '>'); - - if (p == NULL) break; - - ++p; /* skip '>' */ - while (*p && isspace(*p)) ++p; - if (!*p) break; - - /* i=0, p -> "C4 ..." */ - /* i=1, p -> "C5\n" */ - - if (strncmp(p, "pass", 4) == 0) - /* [..] .. => pass */ - step.type = CHESS_STEP_SPECIAL; - else { - c = p[0] - 'A' + 1; - r = atoi(p + 1); - - if (INVALID_COL(c) || INVALID_ROW(r)) - break; - - step.loc.r = r; - step.loc.c = c; - } - - step.color = i==0 ? BLACK : WHITE; - ChessHistoryAppend(info, &step); - } - } - } -#undef INVALID_ROW -#undef INVALID_COL - return 0; -} - -void -reversi(int s, ChessGameMode mode) -{ - ChessInfo* info = NewChessInfo(&reversi_actions, &reversi_constants, s, mode); - board_t board; - reversi_tag_t tag = { { 2, 2 } }; /* will be overridden */ - - reversi_init_board(board); - - info->board = board; - info->tag = &tag; - - info->cursor.r = 3; - info->cursor.c = 3; - - if (mode == CHESS_MODE_WATCH) - setutmpmode(CHESSWATCHING); - else - setutmpmode(REVERSI); - currutmp->sig = SIG_REVERSI; - - ChessPlay(info); - - DeleteChessInfo(info); -} - -int -reversi_main(void) -{ - return ChessStartGame('r', SIG_REVERSI, "¶Â¥Õ´Ñ"); -} - -int -reversi_personal(void) -{ - reversi(0, CHESS_MODE_PERSONAL); - return 0; -} - -int -reversi_watch(void) -{ - return ChessWatchGame(&reversi, REVERSI, "¶Â¥Õ´Ñ"); -} - -ChessInfo* -reversi_replay(FILE* fp) -{ - ChessInfo *info; - - info = NewChessInfo(&reversi_actions, &reversi_constants, - 0, CHESS_MODE_REPLAY); - - if(!reversi_loadlog(fp, info)) { - DeleteChessInfo(info); - return NULL; - } - - info->board = malloc(sizeof(board_t)); - info->tag = malloc(sizeof(reversi_tag_t)); - - reversi_init_board(info->board); - /* tag will be initialized later */ - - return info; -} diff --git a/mbbsd/screen.c b/mbbsd/screen.c deleted file mode 100644 index 8b518070..00000000 --- a/mbbsd/screen.c +++ /dev/null @@ -1,819 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#if !defined(USE_PFTERM) - -#define o_clear() output(clearbuf,clearbuflen) -#define o_cleol() output(cleolbuf,cleolbuflen) -#define o_scrollrev() output(scrollrev,scrollrevlen) -#define o_standup() output(strtstandout,strtstandoutlen) -#define o_standdown() output(endstandout,endstandoutlen) - -static unsigned short cur_ln = 0, cur_col = 0; -static unsigned char docls; -static unsigned char standing = NA; -static int scrollcnt, tc_col, tc_line; -static unsigned char _typeahead = 1; - -#define MODIFIED (1) /* if line has been modifed, screen output */ -#define STANDOUT (2) /* if this line has a standout region */ - -void -initscr(void) -{ - if (!big_picture) { - big_picture = (screenline_t *) calloc(scr_lns, sizeof(screenline_t)); - docls = YEA; - } -} - -int -resizeterm(int w, int h) -{ - screenline_t *new_picture; - - /* make sure reasonable size */ - h = MAX(24, MIN(100, h)); - w = MAX(80, MIN(200, w)); - - if (h > t_lines && big_picture) { - new_picture = (screenline_t *) - calloc(h, sizeof(screenline_t)); - if (new_picture == NULL) { - syslog(LOG_ERR, "calloc(): %m"); - return 0; - } - memcpy(new_picture, big_picture, t_lines * sizeof(screenline_t)); - free(big_picture); - big_picture = new_picture; - return 1; - } - return 0; -} - -void -move(int y, int x) -{ - if (y < 0) y = 0; - if (y >= t_lines) y = t_lines -1; - if (x < 0) x = 0; - if (x >= ANSILINELEN) x = ANSILINELEN -1; - // assert(y>=0); - // assert(x>=0); - cur_col = x; - cur_ln = y; -} - -void -move_ansi(int y, int x) -{ - // take ANSI length in consideration - register screenline_t *slp; - if (y < 0) y = 0; - if (y >= t_lines) y = t_lines -1; - if (x < 0) x = 0; - if (x >= ANSILINELEN) x = ANSILINELEN -1; - - cur_ln = y; - cur_col = x; - - if (y >= scr_lns || x < 1) - return; - - slp = &big_picture[y]; - if (slp->len < 1) - return; - - slp->data[slp->len] = 0; - x += (strlen((char*)slp->data) - strlen_noansi((char*)slp->data)); - cur_col = x; -} - -void -getyx(int *y, int *x) -{ - *y = cur_ln; - *x = cur_col; -} - -void -getyx_ansi(int *py, int *px) -{ - // take ANSI length in consideration - register screenline_t *slp; - int y = cur_ln, x = cur_col; - char c = 0; - - if (y < 0) y = 0; - if (y >= t_lines) y = t_lines -1; - if (x < 0) x = 0; - if (x >= ANSILINELEN) x = ANSILINELEN -1; - - *py = y; *px = x; - - if (y >= scr_lns || x < 1) - return; - - slp = &big_picture[y]; - if (slp->len < 1) - return; - c = slp->data[x]; - *px += (strlen((char*)slp->data) - strlen_noansi((char*)slp->data)); - slp->data[x] = c; -} - -static inline -screenline_t* GetCurrentLine(){ - register int i = cur_ln + roll; - if(i >= scr_lns) - i %= scr_lns; - return &big_picture[i]; -} - -static void -rel_move(int was_col, int was_ln, int new_col, int new_ln) -{ - if (new_ln >= t_lines || new_col >= t_columns) - return; - - tc_col = new_col; - tc_line = new_ln; - if (new_col == 0) { - if (new_ln == was_ln) { - if (was_col) - ochar('\r'); - return; - } else if (new_ln == was_ln + 1) { - ochar('\n'); - if (was_col) - ochar('\r'); - return; - } - } - if (new_ln == was_ln) { - if (was_col == new_col) - return; - - if (new_col == was_col - 1) { - ochar(Ctrl('H')); - return; - } - } - do_move(new_col, new_ln); -} - -static void -standoutput(const char *buf, int ds, int de, int sso, int eso) -{ - int st_start, st_end; - - if (eso <= ds || sso >= de) { - output(buf + ds, de - ds); - } else { - st_start = MAX(sso, ds); - st_end = MIN(eso, de); - if (sso > ds) - output(buf + ds, sso - ds); - o_standup(); - output(buf + st_start, st_end - st_start); - o_standdown(); - if (de > eso) - output(buf + eso, de - eso); - } -} - -void -redrawwin(void) -{ - register screenline_t *bp; - register int i, j; - int len; - - o_clear(); - for (tc_col = tc_line = i = 0, j = roll; i < scr_lns; i++, j++) { - if (j >= scr_lns) - j = 0; - bp = &big_picture[j]; - if ((len = bp->len)) { - rel_move(tc_col, tc_line, 0, i); - -#ifdef DBCSAWARE - if (!(bp->mode & STANDOUT) && - (cuser.uflag & DBCS_NOINTRESC) && - DBCS_RemoveIntrEscape(bp->data, &len)) - { - // if anything changed, dirty whole line. - bp->len = len; - } -#endif // DBCSAWARE - - if (bp->mode & STANDOUT) { - standoutput((char *)bp->data, 0, len, bp->sso, bp->eso); - } - else - output((char *)bp->data, len); - tc_col += len; - if (tc_col >= t_columns) { - if (automargins) - tc_col = t_columns - 1; - else { - tc_col -= t_columns; - tc_line++; - if (tc_line >= t_lines) - tc_line = b_lines; - } - } - bp->mode &= ~(MODIFIED); - bp->oldlen = len; - } - } - rel_move(tc_col, tc_line, cur_col, cur_ln); - docls = scrollcnt = 0; - oflush(); -} - -int -typeahead(int fd) -{ - switch(fd) - { - case TYPEAHEAD_NONE: - _typeahead = 0; - break; - case TYPEAHEAD_STDIN: - _typeahead = 1; - break; - default: // shall never reach here - assert(NULL); - break; - } - return 0; -} - -void -refresh(void) -{ - if (num_in_buf() && _typeahead) - return; - doupdate(); -} - -void -doupdate(void) -{ - /* TODO remove unnecessary refresh() call, to save CPU time */ - register screenline_t *bp = big_picture; - register int i, j; - int len; - if ((docls) || (abs(scrollcnt) >= (scr_lns - 3))) { - redrawwin(); - return; - } - if (scrollcnt < 0) { - if (!scrollrevlen) { - redrawwin(); - return; - } - rel_move(tc_col, tc_line, 0, 0); - do { - o_scrollrev(); - } while (++scrollcnt); - } else if (scrollcnt > 0) { - rel_move(tc_col, tc_line, 0, b_lines); - do { - ochar('\n'); - } while (--scrollcnt); - } - for (i = 0, j = roll; i < scr_lns; i++, j++) { - if (j >= scr_lns) - j = 0; - bp = &big_picture[j]; - len = bp->len; - - if (bp->mode & MODIFIED && bp->smod < len) - { - bp->mode &= ~(MODIFIED); - -#ifdef DBCSAWARE - if (!(bp->mode & STANDOUT) && - (cuser.uflag & DBCS_NOINTRESC) && - DBCS_RemoveIntrEscape(bp->data, &len)) - { - // if anything changed, dirty whole line. - bp->len = len; - bp->smod = 0; bp->emod = len; - } -#endif // DBCSAWARE - -#if 0 - // disabled now, bugs: - // (1) input number (goto) in bbs list (search_num) - // (2) some empty lines becomes weird (eg, b_config) - // - // more effort to determine ANSI smod - if (bp->smod > 0) - { - int iesc; - for (iesc = bp->smod-1; iesc >= 0; iesc--) - { - if (bp->data[iesc] == ESC_CHR) - { - bp->smod = 0;// iesc; - bp->emod =len -1; - break; - } - } - } -#endif - - if (bp->emod >= len) - bp->emod = len - 1; - rel_move(tc_col, tc_line, bp->smod, i); - - if (bp->mode & STANDOUT) - standoutput((char *)bp->data, bp->smod, bp->emod + 1, - bp->sso, bp->eso); - else - output((char *)&bp->data[bp->smod], bp->emod - bp->smod + 1); - tc_col = bp->emod + 1; - if (tc_col >= t_columns) { - if (automargins) - tc_col = t_columns - 1; - else { - tc_col -= t_columns; - tc_line++; - if (tc_line >= t_lines) - tc_line = b_lines; - } - } - } - if (bp->oldlen > len) { - /* XXX len/oldlen also count the length of escape sequence, - * before we fix it, we must print ANSI_CLRTOEND everywhere */ - rel_move(tc_col, tc_line, len, i); - o_cleol(); - } - bp->oldlen = len; - } - - rel_move(tc_col, tc_line, cur_col, cur_ln); - - oflush(); -} - -void -clear(void) -{ - register screenline_t *slp; - - register int i; - - docls = YEA; - cur_col = cur_ln = roll = 0; - for(i=0; i<scr_lns; i++) { - slp = &big_picture[i]; - slp->mode = slp->len = slp->oldlen = 0; - } -} - -void -clrtoeol(void) -{ - register screenline_t *slp = GetCurrentLine(); - register int ln; - - standing = NA; - - if (cur_col <= slp->sso) - slp->mode &= ~STANDOUT; - - /* - if (cur_col == 0) // TODO and contains ANSI - { - // workaround poor ANSI issue - size_t sz = (slp->len > slp->oldlen) ? slp->len : slp->oldlen; - sz = (sz < ANSILINELEN) ? sz : ANSILINELEN; - memset(slp->data, ' ', sz); - slp->len = 0; - return; - } - */ - - if (cur_col > slp->oldlen) { - for (ln = slp->len; ln <= cur_col; ln++) - slp->data[ln] = ' '; - } - if (cur_col < slp->oldlen) { - for (ln = slp->len; ln >= cur_col; ln--) - slp->data[ln] = ' '; - } - slp->len = cur_col; -} - - -void newwin (int nlines, int ncols, int y, int x) -{ - int i=0, oy, ox; - getyx(&oy, &ox); - - while (nlines-- > 0) - { - move_ansi(y++, x); - for (i = 0; i < ncols; i++) - outc(' '); - } - move(oy, ox); -} - -/** - * ±q¥Ø«eªº¦æ¼Æ(scr_ln) clear ¨ì²Ä line ¦æ - */ -void -clrtoln(int line) -{ - register screenline_t *slp; - register int i, j; - - for (i = cur_ln, j = i + roll; i < line; i++, j++) { - if (j >= scr_lns) - j -= scr_lns; - slp = &big_picture[j]; - slp->mode = slp->len = 0; - if (slp->oldlen) - slp->oldlen = scr_cols; - } -} - -/** - * ±q¥Ø«eªº¦æ¼Æ(scr_ln) clear ¨ì©³ - */ -inline void -clrtobot(void) -{ - clrtoln(scr_lns); -} - -void -outc(unsigned char c) -{ - register screenline_t *slp = GetCurrentLine(); - register int i; - - // 0xFF is invalid for most cases (even DBCS), - if (c == 0xFF || c == 0x00) - return; - - if (c == '\n' || c == '\r') { - if (standing) { - slp->eso = MAX(slp->eso, cur_col); - standing = NA; - } - if ((i = cur_col - slp->len) > 0) - memset(&slp->data[slp->len], ' ', i + 1); - slp->len = cur_col; - cur_col = 0; - if (cur_ln < scr_lns) - cur_ln++; - return; - } - /* - * else if(c != ESC_CHR && !isprint2(c)) { c = '*'; //substitute a '*' for - * non-printable } - */ - if (cur_col >= slp->len) { - for (i = slp->len; i < cur_col; i++) - slp->data[i] = ' '; - slp->data[cur_col] = '\0'; - slp->len = cur_col + 1; - } - - if (slp->data[cur_col] != c) { - slp->data[cur_col] = c; - if (!(slp->mode & MODIFIED)) - slp->smod = slp->emod = cur_col; - slp->mode |= MODIFIED; - if (cur_col > slp->emod) - slp->emod = cur_col; - if (cur_col < slp->smod) - slp->smod = cur_col; - } -#if 1 - if(cur_col < scr_cols) - cur_col++; -#else - /* vvv commented by piaip: but SCR_COLS is 511 > unsigned char! */ - /* this comparison is always false (cur_col is unsigned char and scr_cols - * is 511). */ - if (++cur_col >= scr_cols) { - if (standing && (slp->mode & STANDOUT)) { - standing = 0; - slp->eso = MAX(slp->eso, cur_col); - } - cur_col = 0; - if (cur_ln < scr_lns) - cur_ln++; - } -#endif -} - -void -outs(const char *str) -{ - if (!str) - return; - while (*str) { - outc(*str++); - } -} - -void -outns(const char *str, int n) -{ - if (!str) - return; - while (*str && n-- > 0) { - outc(*str++); - } -} - -void -outstr(const char *str) -{ - // XXX TODO cannot prepare DBCS-ready environment? - - outs(str); -} - -void -addch(unsigned char c) -{ - outc(c); -} - -void -addstr(const char *s) -{ - outs(s); -} - -void -addnstr(const char *s, int n) -{ - outns(s, n); -} - -void -addstring(const char *s) -{ - outs(s); -} - - -void -scroll(void) -{ - scrollcnt++; - if (++roll >= scr_lns) - roll = 0; - move(b_lines, 0); - clrtoeol(); -} - -void -rscroll(void) -{ - scrollcnt--; - if (--roll < 0) - roll = b_lines; - move(0, 0); - clrtoeol(); -} - -void -region_scroll_up(int top, int bottom) -{ - int i; - - if (top > bottom) { - i = top; - top = bottom; - bottom = i; - } - if (top < 0 || bottom >= scr_lns) - return; - - for (i = top; i < bottom; i++) - big_picture[i] = big_picture[i + 1]; - memset(big_picture + i, 0, sizeof(*big_picture)); - memset(big_picture[i].data, ' ', scr_cols); - save_cursor(); - change_scroll_range(top, bottom); - do_move(0, bottom); - scroll_forward(); - change_scroll_range(0, scr_lns - 1); - restore_cursor(); - refresh(); -} - -void -standout(void) -{ - if (!standing && strtstandoutlen) { - register screenline_t *slp; - - slp = GetCurrentLine(); - standing = YEA; - slp->sso = slp->eso = cur_col; - slp->mode |= STANDOUT; - } -} - -void -standend(void) -{ - if (standing && strtstandoutlen) { - register screenline_t *slp; - - slp = GetCurrentLine(); - standing = NA; - slp->eso = MAX(slp->eso, cur_col); - } -} - -// readback -int -instr(char *str) -{ - register screenline_t *slp = GetCurrentLine(); - *str = 0; - if (!slp) - return 0; - slp->data[slp->len] = 0; - strip_ansi(str, (char*)slp->data, STRIP_ALL); - return strlen(str); -} - -int -innstr(char *str, int n) -{ - register screenline_t *slp = GetCurrentLine(); - char buf[ANSILINELEN]; - *str = 0; - if (!slp) - return 0; - slp->data[slp->len] = 0; - strip_ansi(buf, (char*)slp->data, STRIP_ALL); - buf[ANSILINELEN] = 0; - strlcpy(str, buf, n); - return strlen(str); -} - -int -inansistr(char *str, int n) -{ - register screenline_t *slp = GetCurrentLine(); - *str = 0; - if (!slp) - return 0; - slp->data[slp->len] = 0; - strlcpy(str, (char*)slp->data, n); - return strlen(str); -} - -// level: -// -1 - bold out -// 0 - dark text -// 1 - text -// 2 - no highlight (not implemented) -void -grayout(int y, int end, int level) -{ - register screenline_t *slp = NULL; - char buf[ANSILINELEN]; - int i = 0; - - if (y < 0) y = 0; - if (end > b_lines) end = b_lines; - - // TODO change to y <= end someday - // loop lines - for (; y <= end; y ++) - { - // modify by scroll - i = y + roll; - if (i < 0) - i += scr_lns; - else if (i >= scr_lns) - i %= scr_lns; - - slp = &big_picture[i]; - - if (slp->len < 1) - continue; - - if (slp->len >= ANSILINELEN) - slp->len = ANSILINELEN -1; - - // tweak slp - slp->data[slp->len] = 0; - slp->mode &= ~STANDOUT; - slp->mode |= MODIFIED; - slp->oldlen = 0; - slp->sso = slp->eso = 0; - slp->smod = 0; - - // make slp->data a pure string - for (i=0; i<slp->len; i++) - { - if (!slp->data[i]) - slp->data[i] = ' '; - } - - slp->len = strip_ansi(buf, (char*)slp->data, STRIP_ALL); - buf[slp->len] = 0; - - switch(level) - { - case GRAYOUT_DARK: // dark text - case GRAYOUT_BOLD:// bold text - // basically, in current system slp->data will - // not exceed t_columns. buffer overflow is impossible. - // but to make it more robust, let's quick check here. - // of course, t_columns should always be far smaller. - if (strlen((char*)slp->data) > t_columns) - slp->data[t_columns] = 0; - strcpy((char*)slp->data, - level < 0 ? ANSI_COLOR(1) : ANSI_COLOR(1;30;40)); - strcat((char*)slp->data, buf); - strcat((char*)slp->data, ANSI_RESET ANSI_CLRTOEND); - slp->len = strlen((char*)slp->data); - break; - - case GRAYOUT_NORM: // Plain text - memcpy(slp->data, buf, slp->len + 1); - break; - } - slp->emod = slp->len -1; - } -} - -static size_t screen_backupsize(int len, const screenline_t *bp) -{ - int i; - size_t sum = 0; - for(i = 0; i < len; i++) - sum += ((char*)&bp[i].data - (char*)&bp[i]) + bp[i].len; - return sum; -} - -void scr_dump(screen_backup_t *old) -{ - int i; - size_t offset = 0; - void *buf; - screenline_t* bp = big_picture; - - buf = old->raw_memory = malloc(screen_backupsize(t_lines, big_picture)); - - old->col = t_columns; - old->row = t_lines; - getyx(&old->y, &old->x); - - for(i = 0; i < t_lines; i++) { - /* backup header */ - memcpy((char*)buf + offset, &bp[i], ((char*)&bp[i].data - (char*)&bp[i])); - offset += ((char*)&bp[i].data - (char*)&bp[i]); - - /* backup body */ - memcpy((char*)buf + offset, &bp[i].data, bp[i].len); - offset += bp[i].len; - } -} - -void scr_restore(const screen_backup_t *old) -{ - int i; - size_t offset=0; - void *buf = old->raw_memory; - screenline_t* bp = big_picture; - const int len = MIN(old->row, t_lines); - - for(i = 0; i < len; i++) { - /* restore header */ - memcpy(&bp[i], (char*)buf + offset, ((char*)&bp[i].data - (char*)&bp[i])); - offset += ((char*)&bp[i].data - (char*)&bp[i]); - - /* restore body */ - memcpy(&bp[i].data, (char*)buf + offset, bp[i].len); - offset += bp[i].len; - } - - free(old->raw_memory); - move(old->y, old->x); - redrawwin(); -} - -#endif // !defined(USE_PFTERM) - -/* vim:sw=4 - */ diff --git a/mbbsd/stuff.c b/mbbsd/stuff.c deleted file mode 100644 index 2349a68d..00000000 --- a/mbbsd/stuff.c +++ /dev/null @@ -1,828 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -/* ----------------------------------------------------- */ -/* set file path for boards/user home */ -/* ----------------------------------------------------- */ -static const char * const str_home_file = "home/%c/%s/%s"; -static const char * const str_board_file = "boards/%c/%s/%s"; -static const char * const str_board_n_file = "boards/%c/%s/%s.%d"; - - -static const char * const str_dotdir = FN_DIR; - -/* XXX set*() all assume buffer size = PATHLEN */ -void -sethomepath(char *buf, const char *userid) -{ - assert(is_validuserid(userid)); - snprintf(buf, PATHLEN, "home/%c/%s", userid[0], userid); -} - -void -sethomedir(char *buf, const char *userid) -{ - assert(is_validuserid(userid)); - snprintf(buf, PATHLEN, str_home_file, userid[0], userid, str_dotdir); -} - -void -sethomeman(char *buf, const char *userid) -{ - assert(is_validuserid(userid)); - snprintf(buf, PATHLEN, str_home_file, userid[0], userid, "man"); -} - - -void -sethomefile(char *buf, const char *userid, const char *fname) -{ - assert(is_validuserid(userid)); - assert(fname[0]); - snprintf(buf, PATHLEN, str_home_file, userid[0], userid, fname); -} - -void -setuserfile(char *buf, const char *fname) -{ - assert(is_validuserid(cuser.userid)); - assert(fname[0]); - snprintf(buf, PATHLEN, str_home_file, cuser.userid[0], cuser.userid, fname); -} - -void -setapath(char *buf, const char *boardname) -{ - //assert(boardname[0]); - snprintf(buf, PATHLEN, "man/boards/%c/%s", boardname[0], boardname); -} - -void -setadir(char *buf, const char *path) -{ - //assert(path[0]); - snprintf(buf, PATHLEN, "%s/%s", path, str_dotdir); -} - -void -setbpath(char *buf, const char *boardname) -{ - //assert(boardname[0]); - snprintf(buf, PATHLEN, "boards/%c/%s", boardname[0], boardname); -} - -void -setbdir(char *buf, const char *boardname) -{ - //assert(boardname[0]); - snprintf(buf, PATHLEN, str_board_file, boardname[0], boardname, - (currmode & MODE_DIGEST ? fn_mandex : str_dotdir)); -} - -void -setbfile(char *buf, const char *boardname, const char *fname) -{ - //assert(boardname[0]); - assert(fname[0]); - snprintf(buf, PATHLEN, str_board_file, boardname[0], boardname, fname); -} - -void -setbnfile(char *buf, const char *boardname, const char *fname, int n) -{ - //assert(boardname[0]); - assert(fname[0]); - snprintf(buf, PATHLEN, str_board_n_file, boardname[0], boardname, fname, n); -} - -/* - * input direct - * output buf: copy direct - * fname: direct ªºÀɦW³¡¤À - */ -void -setdirpath(char *buf, const char *direct, const char *fname) -{ - char *p; - strcpy(buf, direct); - p = strrchr(buf, '/'); - assert(p); - strlcpy(p + 1, fname, PATHLEN-(p+1-buf)); -} - -/** - * µ¹©w¤å³¹¼ÐÃD title¡A¶Ç¦^«ü¨ì¥DÃDªº³¡¤Àªº«ü¼Ð¡C - * @param title - */ -char * -subject(char *title) -{ - if (!strncasecmp(title, str_reply, 3)) { - title += 3; - if (*title == ' ') - title++; - } - return title; -} - -int is_validuserid(const char *id) -{ - int len, i; - if(id==NULL) - return 0; - len = strlen(id); - - if (len < 2 || len>IDLEN) - return 0; - - if (!isalpha(id[0])) - return 0; - for (i = 1; i < len; i++) - if (!isalnum(id[i])) - return 0; - return 1; -} - -int -is_uBM(const char *list, const char *id) -{ - register int len; - - if (list[0] == '[') - list++; - if (list[0] > ' ') { - len = strlen(id); - do { - if (!strncasecmp(list, id, len)) { - list += len; - if ((*list == 0) || (*list == '/') || - (*list == ']') || (*list == ' ')) - return 1; - } - if ((list = strchr(list, '/')) != NULL) - list++; - else - break; - } while (1); - } - return 0; -} - -int -is_BM(const char *list) -{ - if (is_uBM(list, cuser.userid)) { - cuser.userlevel |= PERM_BM; /* Ptt ¦Û°Ê¥[¤WBMªºÅv§Q */ - return 1; - } - return 0; -} - -int -userid_is_BM(const char *userid, const char *list) -{ - register int ch, len; - - // TODO merge with is_uBM - ch = list[0]; - if ((ch > ' ') && (ch < 128)) { - len = strlen(userid); - do { - if (!strncasecmp(list, userid, len)) { - ch = list[len]; - if ((ch == 0) || (ch == '/') || (ch == ']')) - return 1; - } - while ((ch = *list++)) { - if (ch == '/') - break; - } - } while (ch); - } - return 0; -} - -int -belong(const char *filelist, const char *key) -{ - return file_exist_record(filelist, key); -} - - -#ifndef _BBS_UTIL_C_ /* getdata_buf */ -time4_t -gettime(int line, time4_t dt, const char*head) -{ - char yn[7]; - int i; - struct tm *ptime = localtime4(&dt), endtime; - time_t t; - - memcpy(&endtime, ptime, sizeof(struct tm)); - snprintf(yn, sizeof(yn), "%4d", ptime->tm_year + 1900); - move(line, 0); outs(head); - i=strlen(head); - do { - getdata_buf(line, i, " ¦è¤¸¦~:", yn, 5, LCECHO); - // signed: limited on (2037, ...) - // unsigned: limited on (..., 1970) - // let's restrict inside the boundary. - } while ((endtime.tm_year = atoi(yn) - 1900) < 70 || endtime.tm_year > 135); - snprintf(yn, sizeof(yn), "%d", ptime->tm_mon + 1); - do { - getdata_buf(line, i+15, "¤ë:", yn, 3, LCECHO); - } while ((endtime.tm_mon = atoi(yn) - 1) < 0 || endtime.tm_mon > 11); - snprintf(yn, sizeof(yn), "%d", ptime->tm_mday); - do { - getdata_buf(line, i+24, "¤é:", yn, 3, LCECHO); - } while ((endtime.tm_mday = atoi(yn)) < 1 || endtime.tm_mday > 31); - snprintf(yn, sizeof(yn), "%d", ptime->tm_hour); - do { - getdata_buf(line, i+33, "®É(0-23):", yn, 3, LCECHO); - } while ((endtime.tm_hour = atoi(yn)) < 0 || endtime.tm_hour > 23); - t = mktime(&endtime); - /* saturation check */ - if(t < 0) - t = 1; - if(t > INT_MAX) - t = INT_MAX; - return t; -} - -// synchronize 'now' -void syncnow(void) -{ -#ifdef OUTTA_TIMER - now = SHM->GV2.e.now; -#else - now = time(0); -#endif -} - -#endif - - -#ifndef _BBS_UTIL_C_ -/* ³o¤@°Ï³£¬O¦³Ãö©óµe±³B²zªº, ¬G _BBS_UTIL_C_ ¤£¶·n */ - -#ifdef PLAY_ANGEL -void -pressanykey_or_callangel(){ - int ch; - - outmsg( - ANSI_COLOR(1;34;44) " ¢e¢e¢e¢e " - ANSI_COLOR(32) "H " ANSI_COLOR(36) "©I¥s¤p¤Ñ¨Ï" ANSI_COLOR(34) - " ¢e¢e¢e¢e" ANSI_COLOR(37;44) " ½Ð«ö " ANSI_COLOR(36) "ªÅ¥ÕÁä " - ANSI_COLOR(37) "Ä~Äò " ANSI_COLOR(1;34) - "¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e¢e " ANSI_RESET); - do { - ch = igetch(); - if (ch == 'h' || ch == 'H'){ - CallAngel(); - break; - } - } while ((ch != ' ') && (ch != KEY_LEFT) && (ch != '\r') && (ch != '\n')); - move(b_lines, 0); - clrtoeol(); - refresh(); -} -#endif - -/** - * µ¹ printf format ªº°Ñ¼Æ¡A¦L¨ì³Ì©³¤U¤@¦æ¡C - * ¶Ç¦^¨Ï¥ÎªÌªº¿ï¾Ü(char)¡C - */ -char -getans(const char *fmt,...) -{ - char msg[256]; - char ans[3]; - va_list ap; - va_start(ap, fmt); - vsnprintf(msg , sizeof(msg), fmt, ap); - va_end(ap); - - getdata(b_lines, 0, msg, ans, sizeof(ans), LCECHO); - return ans[0]; -} - -int -getkey(const char *fmt,...) -{ - char msg[256], i; - va_list ap; - va_start(ap, fmt); - i = vsnprintf(msg , sizeof(msg), fmt, ap); - va_end(ap); - return vmsg(msg); -} - -static const char *msg_pressanykey_full = - ANSI_COLOR(37;44) " ½Ð«ö" ANSI_COLOR(36) " ¥ô·NÁä " ANSI_COLOR(37) "Ä~Äò " ANSI_COLOR(34); -#define msg_pressanykey_full_len (18) - - // what is 200/1431/506/201? -static const char* msg_pressanykey_trail = - ANSI_COLOR(33;46) " [«ö¥ô·NÁäÄ~Äò] " ANSI_RESET; -#define msg_pressanykey_trail_len (16+1+4) /* 4 for head */ - -int -vmsg(const char *msg) -{ - int len = msg ? strlen(msg) : 0; - int i = 0; - - if(len == 0) msg = NULL; - - move(b_lines, 0); - clrtoeol(); - - if(!msg) - { - /* msg_pressanykey_full */ - int w = (t_columns - msg_pressanykey_full_len - 8) / 2; - int pad = 0; - - outs(ANSI_COLOR(1;34;44) " "); - pad += 1; - for (i = 0; i < w; i += 2) - outs("¢e"), pad+=2; - outs(msg_pressanykey_full), pad+= msg_pressanykey_full_len; - /* pad now points to position of current cursor. */ - pad = t_columns - pad -2 ; - /* pad is now those left . */ - if (pad > 0) - { - for (i = 0; i <= pad-2; i += 2) - outs("¢e"); - if (i == pad-1) - outs(" "); - } - outs(ANSI_RESET); - } else { - /* msg_pressanykey_trail */ - outs(ANSI_COLOR(1;36;44) " ¡» "); - if(len >= t_columns - msg_pressanykey_trail_len) - len = t_columns - msg_pressanykey_trail_len; - while (i++ < len) - outc(*msg++); - i--; - while (i++ < t_columns - msg_pressanykey_trail_len) - outc(' '); - outs(msg_pressanykey_trail); - } - - do { - i = igetch(); - } while( i == 0 ); - - move(b_lines, 0); - clrtoeol(); - return i; -} - -int -vmsgf(const char *fmt,...) -{ - char msg[256]; - va_list ap; - va_start(ap, fmt); - vsnprintf(msg, sizeof(msg), fmt, ap); - va_end(ap); - msg[sizeof(msg)-1] = 0; - return vmsg(msg); -} - -/** - * ±q²Ä y ¦C¶}©l show ¥X filename Àɮפ¤ªº«e lines ¦æ¡C - * mode ¬° output ªº¼Ò¦¡¡A°Ñ¼Æ¦P strip_ansi¡C - * @param filename - * @param x - * @param lines - * @param mode: SHOWFILE_*, see modes.h - * @return ¥¢±Ñ¶Ç¦^ 0¡A§_«h¬° 1¡C - * 2 ªí¥Ü¦³ PttPrints ½X - */ -int -show_file(const char *filename, int y, int lines, int mode) -{ - FILE *fp; - char buf[1024]; - int ret = 1; - int strpmode = STRIP_ALL; - - if (mode & SHOWFILE_ALLOW_COLOR) - strpmode = ONLY_COLOR; - if (mode & SHOWFILE_ALLOW_MOVE) - strpmode = NO_RELOAD; - - if (y >= 0) - move(y, 0); - clrtoln(lines + y); - if ((fp = fopen(filename, "r"))) { - while (fgets(buf, sizeof(buf), fp) && lines--) - { - move(y++, 0); - if (mode == SHOWFILE_RAW) - { - outs(buf); - } - else if ((mode & SHOWFILE_ALLOW_STAR) && (strstr(buf, ESC_STR "*") != NULL)) - { - // because Ptt_prints escapes are not so often, - // let's try harder to detect it. - outs(Ptt_prints(buf, sizeof(buf), strpmode)); - ret = 2; - } else { - // ESC is very common... - strip_ansi(buf, buf, strpmode); - outs(buf); - } - } - fclose(fp); - outs(ANSI_RESET); // prevent some broken Welcome file - } else - return 0; - return ret; -} - -void -bell(void) -{ - char c; - - c = Ctrl('G'); - write(1, &c, 1); -} - -int -search_num(int ch, int max) -{ - int clen = 1, y = b_lines - msg_occupied; - char genbuf[10]; - - genbuf[0] = ch; genbuf[1] = 0; - clen = getdata_buf(y, 0, - " ¸õ¦Ü²Ä´X¶µ: ", genbuf, sizeof(genbuf)-1, NUMECHO); - - move(y, 0); clrtoeol(); - genbuf[clen] = '\0'; - if (genbuf[0] == '\0') - return -1; - clen = atoi(genbuf); - if (clen == 0) - return 0; - if (clen > max) - return max; - return clen - 1; -} - -/** - * ¦b¿Ã¹õ¥ª¤W¨¤ show ¥X "¡ititle¡j" - * @param title - */ -void -stand_title(const char *title) -{ - clear(); - prints(ANSI_COLOR(1;37;46) "¡i %s ¡j" ANSI_RESET "\n", title); -} - -void -cursor_show(int row, int column) -{ - move(row, column); - outs(STR_CURSOR); - move(row, column + 1); -} - -void -cursor_clear(int row, int column) -{ - move(row, column); - outs(STR_UNCUR); -} - -int -cursor_key(int row, int column) -{ - int ch; - - cursor_show(row, column); - ch = igetch(); - move(row, column); - outs(STR_UNCUR); - return ch; -} - -void -printdash(const char *mesg, int msglen) -{ - int head = 0, tail; - - if(msglen <= 0) - msglen = strlen(mesg); - - if (mesg) - head = (msglen + 1) >> 1; - - tail = head; - - while (head++ < t_columns/2-2) - outc('-'); - - if (tail) { - outc(' '); - if(mesg) outs(mesg); - outc(' '); - } - while (tail++ < t_columns/2-2) - outc('-'); - - outc('\n'); -} - -int -log_user(const char *fmt, ...) -{ - char msg[256], filename[256]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(msg , sizeof(msg), fmt, ap); - va_end(ap); - - sethomefile(filename, cuser.userid, "USERLOG"); - return log_filef(filename, LOG_CREAT, "%s: %s %s", cuser.userid, msg, Cdate(&now)); -} - -void -show_help(const char * const helptext[]) -{ - const char *str; - int i; - - clear(); - for (i = 0; (str = helptext[i]); i++) { - if (*str == '\0') - prints(ANSI_COLOR(1) "¡i %s ¡j" ANSI_COLOR(0) "\n", str + 1); - else if (*str == '\01') - prints("\n" ANSI_COLOR(36) "¡i %s ¡j" ANSI_RESET "\n", str + 1); - else - prints(" %s\n", str); - } -#ifdef PLAY_ANGEL - if (HasUserPerm(PERM_LOGINOK)) - pressanykey_or_callangel(); - else -#endif - pressanykey(); -} - -void -show_helpfile(const char *helpfile) -{ - clear(); - show_file((char *)helpfile, 0, b_lines, SHOWFILE_ALLOW_ALL); -#ifdef PLAY_ANGEL - if (HasUserPerm(PERM_LOGINOK)) - pressanykey_or_callangel(); - else -#endif - pressanykey(); -} - -#endif // _BBS_UTIL_C_ - -/* ----------------------------------------------------- */ -/* use mmap() to malloc large memory in CRITICAL_MEMORY */ -/* ----------------------------------------------------- */ -#ifdef CRITICAL_MEMORY -void *MALLOC(int size) -{ - int *p; - p = (int *)mmap(NULL, (size + 4), PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, -1, 0); - p[0] = size; -#if defined(DEBUG) && !defined(_BBS_UTIL_C_) - vmsgf("critical malloc %d bytes", size); -#endif - return (void *)&p[1]; -} - -void FREE(void *ptr) -{ - int size = ((int *)ptr)[-1]; - munmap((void *)(&(((int *)ptr)[-1])), size); -#if defined(DEBUG) && !defined(_BBS_UTIL_C_) - vmsgf("critical free %d bytes", size); -#endif -} -#endif - - -unsigned -DBCS_StringHash(const char *s) -{ - return fnv1a_32_dbcs_strcase(s, FNV1_32_INIT); -} - -inline int *intbsearch(int key, const int *base0, int nmemb) -{ - /* §ï¦Û /usr/src/lib/libc/stdlib/bsearch.c , - ±Mµ¹·j int array ¥Îªº, ¤£³z¹L compar function ¬G¸û§Ö¨Ç */ - const char *base = (const char *)base0; - size_t lim; - int *p; - - for (lim = nmemb; lim != 0; lim >>= 1) { - p = (int *)(base + (lim >> 1) * 4); - if( key == *p ) - return p; - if( key > *p ){/* key > p: move right */ - base = (char *)p + 4; - lim--; - } /* else move left */ - } - return (NULL); -} - -inline unsigned int * -uintbsearch(const unsigned int key, const unsigned int *base0, const int nmemb) -{ - /* §ï¦Û /usr/src/lib/libc/stdlib/bsearch.c , - ±Mµ¹·j int array ¥Îªº, ¤£³z¹L compar function ¬G¸û§Ö¨Ç */ - const char *base = (const char *)base0; - size_t lim; - unsigned int *p; - - for (lim = nmemb; lim != 0; lim >>= 1) { - p = (unsigned int *)(base + (lim >> 1) * 4); - if( key == *p ) - return p; - if( key > *p ){/* key > p: move right */ - base = (char *)p + 4; - lim--; - } /* else move left */ - } - return (NULL); -} - -/* AIDS */ -aidu_t fn2aidu(char *fn) -{ - aidu_t aidu = 0; - aidu_t type = 0; - aidu_t v1 = 0; - aidu_t v2 = 0; - char *sp = fn; - - if(fn == NULL) - return 0; - - switch(*(sp ++)) - { - case 'M': - type = 0; - break; - case 'G': - type = 1; - break; - default: - return 0; - break; - } - - if(*(sp ++) != '.') - return 0; - v1 = strtoul(sp, &sp, 10); - if(sp == NULL) - return 0; - if(*sp != '.' || *(sp + 1) != 'A') - return 0; - sp += 2; - if(*(sp ++) == '.') - { - v2 = strtoul(sp, &sp, 16); - if(sp == NULL) - return 0; - } - aidu = ((type & 0xf) << 44) | ((v1 & 0xffffffff) << 12) | (v2 & 0xfff); - - return aidu; -} - -/* IMPORTANT: - * size of buf must be at least 8+1 bytes - */ -char *aidu2aidc(char *buf, aidu_t aidu) -{ - const char aidu2aidc_table[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_"; - const int aidu2aidc_tablesize = sizeof(aidu2aidc_table) - 1; - char *sp = buf + 8; - aidu_t v; - - *(sp --) = '\0'; - while(sp >= buf) - { - /* FIXME: ¯à«OÃÒ aidu2aidc_tablesize ¬O 2 ªº¾¦¸ªº¸Ü¡A - ³o¸Ì¥i¥H§ï¥Î bitwise operation °µ */ - v = aidu % aidu2aidc_tablesize; - aidu = aidu / aidu2aidc_tablesize; - *(sp --) = aidu2aidc_table[v]; - } - return buf; -} - -/* IMPORTANT: - * size of fn must be at least FNLEN bytes - */ -char *aidu2fn(char *fn, aidu_t aidu) -{ - aidu_t type = ((aidu >> 44) & 0xf); - aidu_t v1 = ((aidu >> 12) & 0xffffffff); - aidu_t v2 = (aidu & 0xfff); - - if(fn == NULL) - return NULL; - snprintf(fn, FNLEN - 1, "%c.%d.A.%03X", ((type == 0) ? 'M' : 'G'), (unsigned int)v1, (unsigned int)v2); - fn[FNLEN - 1] = '\0'; - return fn; -} - -aidu_t aidc2aidu(char *aidc) -{ - char *sp = aidc; - aidu_t aidu = 0; - - if(aidc == NULL) - return 0; - - while(*sp != '\0' && /* ignore trailing spaces */ *sp != ' ') - { - aidu_t v = 0; - /* FIXME: ¬dªíªk·|¤£·|¤ñ¸û§Ö¡H */ - if(*sp >= '0' && *sp <= '9') - v = *sp - '0'; - else if(*sp >= 'A' && *sp <= 'Z') - v = *sp - 'A' + 10; - else if(*sp >= 'a' && *sp <= 'z') - v = *sp - 'a' + 36; - else if(*sp == '-') - v = 62; - else if(*sp == '_') - v = 63; - else - return 0; - aidu <<= 6; - aidu |= (v & 0x3f); - sp ++; - } - - return aidu; -} - -int search_aidu(char *bfile, aidu_t aidu) -{ - char fn[FNLEN]; - int fd; - fileheader_t fhs[64]; - int len, i; - int pos = 0; - int found = 0; - int lastpos = 0; - - if(aidu2fn(fn, aidu) == NULL) - return -1; - if((fd = open(bfile, O_RDONLY, 0)) < 0) - return -1; - - while(!found && (len = read(fd, fhs, sizeof(fhs))) > 0) - { - len /= sizeof(fileheader_t); - for(i = 0; i < len; i ++) - { - int l; - if(strcmp(fhs[i].filename, fn) == 0 || - ((aidu & 0xfff) == 0 && (l = strlen(fhs[i].filename)) > 6 && - strncmp(fhs[i].filename, fn, l) == 0)) - { - if(fhs[i].filemode & FILE_BOTTOM) - { - lastpos = pos; - } - else - { - found = 1; - break; - } - } - pos ++; - } - } - close(fd); - - return (found ? pos : (lastpos ? lastpos : -1)); -} -/* end of AIDS */ diff --git a/mbbsd/syspost.c b/mbbsd/syspost.c deleted file mode 100644 index 9ced9918..00000000 --- a/mbbsd/syspost.c +++ /dev/null @@ -1,146 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -int -post_msg(const char *bname, const char *title, const char *msg, const char *author) -{ - FILE *fp; - int bid; - fileheader_t fhdr; - char fname[PATHLEN]; - - /* ¦b bname ªOµoªí·s¤å³¹ */ - setbpath(fname, bname); - stampfile(fname, &fhdr); - fp = fopen(fname, "w"); - - if (!fp) - return -1; - - fprintf(fp, "§@ªÌ: %s ¬ÝªO: %s\n¼ÐÃD: %s \n", author, bname, title); - fprintf(fp, "®É¶¡: %s\n", ctime4(&now)); - - /* ¤å³¹ªº¤º®e */ - fputs(msg, fp); - fclose(fp); - - /* ±NÀÉ®×¥[¤J¦Cªí */ - strlcpy(fhdr.title, title, sizeof(fhdr.title)); - strlcpy(fhdr.owner, author, sizeof(fhdr.owner)); - setbdir(fname, bname); - if (append_record(fname, &fhdr, sizeof(fhdr)) != -1) - if ((bid = getbnum(bname)) > 0) - setbtotal(bid); - return 0; -} - -int -post_file(const char *bname, const char *title, const char *filename, const char *author) -{ - int size = dashs(filename); - char *msg; - FILE *fp; - - if (size <= 0) - return -1; - if (!(fp = fopen(filename, "r"))) - return -1; - msg = (char *)malloc(size + 1); - size = fread(msg, 1, size, fp); - msg[size] = 0; - size = post_msg(bname, title, msg, author); - fclose(fp); - free(msg); - return size; -} - -void -post_change_perm(int oldperm, int newperm, const char *sysopid, const char *userid) -{ - char genbuf[(NUMPERMS+1) * STRLEN*2] = "", reason[30] = ""; - char title[TTLEN+1]; - char *s = genbuf; - int i, flag = 0; - - // generate log (warning: each line should <= STRLEN*2) - for (i = 0; i < NUMPERMS; i++) { - if (((oldperm >> i) & 1) != ((newperm >> i) & 1)) { - sprintf(s, " ¯¸ªø" ANSI_COLOR(1;32) "%s%s%s%s" ANSI_RESET "ªºÅv\n", - sysopid, - (((oldperm >> i) & 1) ? ANSI_COLOR(1;33) "Ãö³¬" : ANSI_COLOR(1;33) "¶}±Ò"), - userid, str_permid[i]); - s += strlen(s); - flag++; - } - } - - if (!flag) // nothing changed - return; - - clrtobot(); - clear(); - while (!getdata(5, 0, "½Ð¿é¤J²z¥Ñ¥H¥Üt³d¡G", - reason, sizeof(reason), DOECHO)); - sprintf(s, "\n " ANSI_COLOR(1;37) "¯¸ªø%sקïÅv²z¥Ñ¬O¡G%s" ANSI_RESET, - cuser.userid, reason); - - snprintf(title, sizeof(title), "[¤½¦w³ø§i] ¯¸ªø%sקï%sÅv³ø§i", - cuser.userid, userid); - - post_msg(GLOBAL_SECURITY, title, genbuf, "[¨t²Î¦w¥þ§½]"); -} - -void -post_violatelaw(const char *crime, const char *police, const char *reason, const char *result) -{ - char title[TTLEN+1]; - char msg[200]; - - snprintf(title, sizeof(title), "[³ø§i] %s:%-*s §P¨M", crime, - (int)(37 - strlen(reason) - strlen(crime)), reason); - - snprintf(msg, sizeof(msg), - ANSI_COLOR(1;32) "%s" ANSI_RESET "§P¨M¡G\n" - " " ANSI_COLOR(1;32) "%s" ANSI_RESET "¦]" ANSI_COLOR(1;35) "%s" ANSI_RESET "¦æ¬°¡A\n" - "¹H¤Ï¥»¯¸¯¸³W¡A³B¥H" ANSI_COLOR(1;35) "%s" ANSI_RESET "¡A¯S¦¹¤½§i\n", - police, crime, reason, result); - - if (!strstr(police, "ĵ¹î")) { - post_msg("PoliceLog", title, msg, "[" BBSMNAME "ªk°|]"); - - snprintf(msg, sizeof(msg), - ANSI_COLOR(1;32) "%s" ANSI_RESET "§P¨M¡G\n" - " " ANSI_COLOR(1;32) "%s" ANSI_RESET "¦]" ANSI_COLOR(1;35) "%s" ANSI_RESET "¦æ¬°¡A\n" - "¹H¤Ï¥»¯¸¯¸³W¡A³B¥H" ANSI_COLOR(1;35) "%s" ANSI_RESET "¡A¯S¦¹¤½§i\n", - "¯¸°Èĵ¹î", crime, reason, result); - } - - post_msg("ViolateLaw", title, msg, "[" BBSMNAME "ªk°|]"); -} - -void -post_newboard(const char *bgroup, const char *bname, const char *bms) -{ - char genbuf[256], title[TTLEN+1]; - - snprintf(title, sizeof(title), "[·sªO¦¨¥ß] %s", bname); - snprintf(genbuf, sizeof(genbuf), - "%s ¶}¤F¤@Ó·sªO %s : %s\n\n·s¥ôªO¥D¬° %s\n\n®¥³ß*^_^*\n", - cuser.userid, bname, bgroup, bms); - - post_msg("Record", title, genbuf, "[¨t²Î]"); -} - -void -post_policelog(const char *bname, const char *atitle, const char *action, const char *reason, const int toggle) -{ - char genbuf[256], title[TTLEN+1]; - - snprintf(title, sizeof(title), "[%s][%s] %s by %s", action, toggle ? "¶}±Ò" : "Ãö³¬", bname, cuser.userid); - snprintf(genbuf, sizeof(genbuf), - "%s (%s) %s %s ¬ÝªO %s ¥\\¯à\nì¦] : %s\n%s%s\n", - cuser.userid, fromhost, toggle ? "¶}±Ò" : "Ãö³¬", bname, action, - reason, atitle ? "¤å³¹¼ÐÃD : " : "", atitle ? atitle : ""); - - post_msg("PoliceLog", title, genbuf, "[¨t²Î]"); -} diff --git a/mbbsd/talk.c b/mbbsd/talk.c deleted file mode 100644 index 70bcdb97..00000000 --- a/mbbsd/talk.c +++ /dev/null @@ -1,3654 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#define QCAST int (*)(const void *, const void *) - -static char * const IdleTypeTable[] = { - "°¸¦bªá§b°Õ", "±¡¤H¨Ó¹q", "³V¹¤¤", "«ô¨£©P¤½", "°²¦ºª¬ºA", "§Ú¦b«ä¦Ò" -}; -static char * const sig_des[] = { - "°«Âû", "²á¤Ñ", "", "¤U´Ñ", "¶H´Ñ", "·t´Ñ", "¤U³ò´Ñ", "¤U¶Â¥Õ´Ñ", -}; -static char * const withme_str[] = { - "½Í¤Ñ", "¤U¤¤l´Ñ", "°«Ãdª«", "¤U¶H´Ñ", "¤U·t´Ñ", "¤U³ò´Ñ", "¤U¶Â¥Õ´Ñ", NULL -}; - -#define MAX_SHOW_MODE 6 -#define M_INT 15 /* monitor mode update interval */ -#define P_INT 20 /* interval to check for page req. in - * talk/chat */ -#define BOARDFRI 1 - -#define TALK_MAXCOL (78) -#define TALK_BUFLEN (TALK_MAXCOL+2) -typedef struct twpic { - unsigned short len; - unsigned char data[TALK_BUFLEN]; // bound to specific size -} twpic_t; - -typedef struct talkwin_t { - int curcol, curln; - int sline, eline; - twpic_t *big_picture; -} talkwin_t; - -typedef struct pickup_t { - userinfo_t *ui; - int friend, uoffset; -} pickup_t; - -/* °O¿ý friend ªº user number */ -// -#define PICKUP_WAYS 8 - -static char * const fcolor[11] = { - "", ANSI_COLOR(36), ANSI_COLOR(32), ANSI_COLOR(1;32), - ANSI_COLOR(33), ANSI_COLOR(1;33), ANSI_COLOR(1;37), ANSI_COLOR(1;37), - ANSI_COLOR(31), ANSI_COLOR(1;35), ANSI_COLOR(1;36) -}; -static char save_page_requestor[40]; -static char page_requestor[40]; - -userinfo_t *uip; - -int -iswritable_stat(const userinfo_t * uentp, int fri_stat) -{ - if (uentp == currutmp) - return 0; - - if (HasUserPerm(PERM_SYSOP)) - return 1; - - if (!HasUserPerm(PERM_LOGINOK) || HasUserPerm(PERM_VIOLATELAW)) - return 0; - - return (uentp->pager != PAGER_ANTIWB && - (fri_stat & HFM || uentp->pager != PAGER_FRIENDONLY)); -} - -int -isvisible_stat(const userinfo_t * me, const userinfo_t * uentp, int fri_stat) -{ - if (!uentp || uentp->userid[0] == 0) - return 0; - - /* to avoid paranoid users get crazy*/ - if (uentp->mode == DEBUGSLEEPING) - return 0; - - if (PERM_HIDE(uentp) && !(PERM_HIDE(me))) /* ¹ï¤èµµ¦âÁô§Î¦Ó§A¨S¦³ */ - return 0; - else if ((me->userlevel & PERM_SYSOP) || - ((fri_stat & HRM) && (fri_stat & HFM))) - /* ¯¸ªø¬Ýªº¨£¥ô¦ó¤H */ - return 1; - - if (uentp->invisible && !(me->userlevel & PERM_SEECLOAK)) - return 0; - - return !(fri_stat & HRM); -} - -int query_online(const char *userid) -{ - userinfo_t *uentp; - - if (!userid || !*userid) - return 0; - - if (!isalnum(*userid)) - return 0; - - if (strchr(userid, '.') || SHM->GV2.e.noonlineuser) - return 0; - - uentp = search_ulist_userid(userid); - - if (!uentp ||!isvisible(currutmp, uentp)) - return 0; - - return 1; -} - -const char * -modestring(const userinfo_t * uentp, int simple) -{ - static char modestr[40]; - static char *const notonline = "¤£¦b¯¸¤W"; - register int mode = uentp->mode; - register char *word; - int fri_stat; - - /* for debugging */ - if (mode >= MAX_MODES) { - syslog(LOG_WARNING, "what!? mode = %d", mode); - word = ModeTypeTable[mode % MAX_MODES]; - } else - word = ModeTypeTable[mode]; - - fri_stat = friend_stat(currutmp, uentp); - if (!(HasUserPerm(PERM_SYSOP) || HasUserPerm(PERM_SEECLOAK)) && - ((uentp->invisible || (fri_stat & HRM)) && - !((fri_stat & HFM) && (fri_stat & HRM)))) - return notonline; - else if (mode == EDITING) { - snprintf(modestr, sizeof(modestr), "E:%s", - ModeTypeTable[uentp->destuid < EDITING ? uentp->destuid : - EDITING]); - word = modestr; - } else if (!mode && *uentp->chatid == 1) { - if (!simple) - snprintf(modestr, sizeof(modestr), "¦^À³ %s", - isvisible_uid(uentp->destuid) ? - getuserid(uentp->destuid) : "ªÅ®ð"); - else - snprintf(modestr, sizeof(modestr), "¦^À³©I¥s"); - } - else if (!mode && *uentp->chatid == 3) - snprintf(modestr, sizeof(modestr), "¤ô²y·Ç³Æ¤¤"); - else if ( -#ifdef NOKILLWATERBALL - uentp->msgcount > 0 -#else - (!mode) && *uentp->chatid == 2 -#endif - ) - if (uentp->msgcount < 10) { - const char *cnum[10] = - {"", "¤@", "¨â", "¤T", "¥|", "¤", - "¤»", "¤C", "¤K", "¤E"}; - snprintf(modestr, sizeof(modestr), - "¤¤%sÁû¤ô²y", cnum[(int)(uentp->msgcount)]); - } else - snprintf(modestr, sizeof(modestr), "¤£¦æ¤F @_@"); - else if (!mode) - return (uentp->destuid == 6) ? uentp->chatid : - IdleTypeTable[(0 <= uentp->destuid && uentp->destuid < 6) ? - uentp->destuid : 0]; - else if (simple) - return word; - else if (uentp->in_chat && mode == CHATING) - snprintf(modestr, sizeof(modestr), "%s (%s)", word, uentp->chatid); - else if (mode == TALK || mode == M_FIVE || mode == CHC || mode == UMODE_GO - || mode == DARK) { - if (!isvisible_uid(uentp->destuid)) /* Leeym ¹ï¤è(µµ¦â)Áô§Î */ - snprintf(modestr, sizeof(modestr), "%s ªÅ®ð", word); - /* Leeym * ¤j®a¦Û¤vµo´§§a¡I */ - else - snprintf(modestr, sizeof(modestr), - "%s %s", word, getuserid(uentp->destuid)); - } else if (mode == CHESSWATCHING) { - snprintf(modestr, sizeof(modestr), "Æ[´Ñ"); - } else if (mode != PAGE && mode != TQUERY) - return word; - else - snprintf(modestr, sizeof(modestr), - "%s %s", word, getuserid(uentp->destuid)); - - return (modestr); -} - -int -set_friend_bit(const userinfo_t * me, const userinfo_t * ui) -{ - int unum, hit = 0; - const int *myfriends; - - /* §PÂ_¹ï¤è¬O§_¬°§ÚªºªB¤Í ? */ - if( intbsearch(ui->uid, me->myfriend, me->nFriends) ) - hit = IFH; - - /* §PÂ_§Ú¬O§_¬°¹ï¤èªºªB¤Í ? */ - if( intbsearch(me->uid, ui->myfriend, ui->nFriends) ) - hit |= HFM; - - /* §PÂ_¹ï¤è¬O§_¬°§Úªº¤³¤H ? */ - myfriends = me->reject; - while ((unum = *myfriends++)) { - if (unum == ui->uid) { - hit |= IRH; - break; - } - } - - /* §PÂ_§Ú¬O§_¬°¹ï¤èªº¤³¤H ? */ - myfriends = ui->reject; - while ((unum = *myfriends++)) { - if (unum == me->uid) { - hit |= HRM; - break; - } - } - return hit; -} - -inline int -he_reject_me(userinfo_t * uin){ - int* iter = uin->reject; - int unum; - while ((unum = *iter++)) { - if (unum == currutmp->uid) { - return 1; - } - } - return 0; -} - -int -reverse_friend_stat(int stat) -{ - int stat1 = 0; - if (stat & IFH) - stat1 |= HFM; - if (stat & IRH) - stat1 |= HRM; - if (stat & HFM) - stat1 |= IFH; - if (stat & HRM) - stat1 |= IRH; - if (stat & IBH) - stat1 |= IBH; - return stat1; -} - -#ifdef OUTTACACHE -int sync_outta_server(int sfd) -{ - int i; - int offset = (int)(currutmp - &SHM->uinfo[0]); - - int cmd, res; - int nfs; - ocfs_t fs[MAX_FRIEND*2]; - - cmd = -2; - if(towrite(sfd, &cmd, sizeof(cmd))<0 || - towrite(sfd, &offset, sizeof(offset))<0 || - towrite(sfd, &currutmp->uid, sizeof(currutmp->uid)) < 0 || - towrite(sfd, currutmp->myfriend, sizeof(currutmp->myfriend))<0 || - towrite(sfd, currutmp->reject, sizeof(currutmp->reject))<0) - return -1; - - if(toread(sfd, &res, sizeof(res))<0) - return -1; - - if(res<0) - return -1; - if(res==2) { - close(sfd); - outs("µn¤J¤ÓÀWÁc, ¬°ÁקK¨t²Ît²ü¹L«, ½Ðµy«á¦A¸Õ\n"); - refresh(); - sleep(30); - log_usies("REJECTLOGIN", NULL); - memset(currutmp, 0, sizeof(userinfo_t)); - exit(0); - } - - if(toread(sfd, &nfs, sizeof(nfs))<0) - return -1; - if(nfs<0 || nfs>MAX_FRIEND*2) { - fprintf(stderr, "invalid nfs=%d\n",nfs); - return -1; - } - - if(toread(sfd, fs, sizeof(fs[0])*nfs)<0) - return -1; - - close(sfd); - - for(i=0; i<nfs; i++) { - if( SHM->uinfo[fs[i].index].uid != fs[i].uid ) - continue; // double check, server may not know user have logout - currutmp->friend_online[currutmp->friendtotal++] - = fs[i].friendstat; - /* XXX: race here */ - if( SHM->uinfo[fs[i].index].friendtotal < MAX_FRIEND ) - SHM->uinfo[fs[i].index].friend_online[ SHM->uinfo[fs[i].index].friendtotal++ ] = fs[i].rfriendstat; - } - - if(res==1) { - vmsg("½Ð¤ÅÀWÁcµn¤J¥H§K³y¦¨¨t²Î¹L«×t²ü"); - } - return 0; -} -#endif - -void login_friend_online(void) -{ - userinfo_t *uentp; - int i, stat, stat1; - int offset = (int)(currutmp - &SHM->uinfo[0]); - -#ifdef OUTTACACHE - int sfd; - /* OUTTACACHE is TOO slow, let's prompt user here. */ - move(b_lines-2, 0); clrtobot(); - outs("\n¥¿¦b§ó·s»P¦P¨B½u¤W¨Ï¥ÎªÌ¤Î¦n¤Í¦W³æ¡A¨t²Ît²ü¶q¤j®É·|»Ý®É¸û¤[...\n"); - refresh(); - - sfd = toconnect(OUTTACACHEHOST, OUTTACACHEPORT); - if(sfd>=0) { - int res=sync_outta_server(sfd); - if(res==0) // sfd will be closed if return 0 - return; - close(sfd); - } -#endif - - for (i = 0; i < SHM->UTMPnumber && currutmp->friendtotal < MAX_FRIEND; i++) { - uentp = (&SHM->uinfo[SHM->sorted[SHM->currsorted][0][i]]); - if (uentp && uentp->uid && (stat = set_friend_bit(currutmp, uentp))) { - stat1 = reverse_friend_stat(stat); - stat <<= 24; - stat |= (int)(uentp - &SHM->uinfo[0]); - currutmp->friend_online[currutmp->friendtotal++] = stat; - if (uentp != currutmp && uentp->friendtotal < MAX_FRIEND) { - stat1 <<= 24; - stat1 |= offset; - uentp->friend_online[uentp->friendtotal++] = stat1; - } - } - } - return; -} - -/* TODO merge with util/shmctl.c logout_friend_online() */ -int -logout_friend_online(userinfo_t * utmp) -{ - int my_friend_idx, thefriend; - int k; - int offset = (int)(utmp - &SHM->uinfo[0]); - userinfo_t *ui; - for(; utmp->friendtotal>0; utmp->friendtotal--) { - if( !(0 <= utmp->friendtotal && utmp->friendtotal < MAX_FRIEND) ) - return 1; - my_friend_idx=utmp->friendtotal-1; - thefriend = (utmp->friend_online[my_friend_idx] & 0xFFFFFF); - utmp->friend_online[my_friend_idx]=0; - - if( !(0 <= thefriend && thefriend < USHM_SIZE) ) - continue; - - ui = &SHM->uinfo[thefriend]; - if(ui->pid==0 || ui==utmp) - continue; - if(ui->friendtotal > MAX_FRIEND || ui->friendtotal<0) - continue; - for (k = 0; k < ui->friendtotal && k < MAX_FRIEND && - (int)(ui->friend_online[k] & 0xFFFFFF) != offset; k++); - if (k < ui->friendtotal && k < MAX_FRIEND) { - ui->friendtotal--; - ui->friend_online[k] = ui->friend_online[ui->friendtotal]; - ui->friend_online[ui->friendtotal] = 0; - } - } - return 0; -} - - -int -friend_stat(const userinfo_t * me, const userinfo_t * ui) -{ - int i, j, hit = 0; - /* ¬ÝªO¦n¤Í */ - if (me->brc_id && ui->brc_id == me->brc_id) { - hit = IBH; - } - for (i = 0; me->friend_online[i] && i < MAX_FRIEND; i++) { - j = (me->friend_online[i] & 0xFFFFFF); - if (VALID_USHM_ENTRY(j) && ui == &SHM->uinfo[j]) { - hit |= me->friend_online[i] >> 24; - break; - } - } - if (PERM_HIDE(ui)) - return hit & ST_FRIEND; - return hit; -} - -int -isvisible_uid(int tuid) -{ - userinfo_t *uentp; - - if (!tuid || !(uentp = search_ulist(tuid))) - return 1; - return isvisible(currutmp, uentp); -} - -/* ¯u¹ê°Ê§@ */ -static void -my_kick(userinfo_t * uentp) -{ - char genbuf[200]; - - getdata(1, 0, msg_sure_ny, genbuf, 4, LCECHO); - clrtoeol(); - if (genbuf[0] == 'y') { - snprintf(genbuf, sizeof(genbuf), - "%s (%s)", uentp->userid, uentp->nickname); - log_usies("KICK ", genbuf); - if ((uentp->pid <= 0 || kill(uentp->pid, SIGHUP) == -1) && (errno == ESRCH)) - purge_utmp(uentp); - outs("½ð¥X¥hÅo"); - } else - outs(msg_cancel); - pressanykey(); -} - -int -my_query(const char *uident) -{ - userec_t muser; - int tuid, fri_stat = 0; - userinfo_t *uentp; - const char *sex[8] = - {MSG_BIG_BOY, MSG_BIG_GIRL, - MSG_LITTLE_BOY, MSG_LITTLE_GIRL, - MSG_MAN, MSG_WOMAN, MSG_PLANT, MSG_MIME}; - static time_t last_query; - - STATINC(STAT_QUERY); - if ((tuid = getuser(uident, &muser))) { - move(1, 0); - clrtobot(); - move(1, 0); - setutmpmode(TQUERY); - currutmp->destuid = tuid; - - if ((uentp = (userinfo_t *) search_ulist(tuid))) - fri_stat = friend_stat(currutmp, uentp); - - prints("¡m¢×¢Ò¼ÊºÙ¡n%s(%s)%*s¡m¸gÀÙª¬ªp¡n%s", - muser.userid, - muser.nickname, - strlen(muser.userid) + strlen(muser.nickname) >= 26 ? 0 : - (int)(26 - strlen(muser.userid) - strlen(muser.nickname)), "", - money_level(muser.money)); - if (uentp && ((fri_stat & HFM && !uentp->invisible) || strcmp(muser.userid,cuser.userid) == 0)) - prints(" ($%d)", muser.money); - outc('\n'); - - prints("¡m¤W¯¸¦¸¼Æ¡n%d¦¸", muser.numlogins); - move(2, 40); -#ifdef ASSESS - prints("¡m¤å³¹½g¼Æ¡n%d½g (Àu:%d/¦H:%d)\n", muser.numposts, muser.goodpost, muser.badpost); -#else - prints("¡m¤å³¹½g¼Æ¡n%d½g\n", muser.numposts); -#endif - - prints(ANSI_COLOR(1;33) "¡m¥Ø«e°ÊºA¡n%-28.28s" ANSI_RESET, - (uentp && isvisible_stat(currutmp, uentp, fri_stat)) ? - modestring(uentp, 0) : "¤£¦b¯¸¤W"); - - outs(((uentp && ISNEWMAIL(uentp)) || load_mailalert(muser.userid)) - ? "¡m¨p¤H«H½c¡n¦³·s¶i«H¥óÁÙ¨S¬Ý\n" : - "¡m¨p¤H«H½c¡n©Ò¦³«H¥ó³£¬Ý¹L¤F\n"); - prints("¡m¤W¦¸¤W¯¸¡n%-28.28s¡m¤W¦¸¬G¶m¡n%s\n", - Cdate(&muser.lastlogin), - (muser.lasthost[0] ? muser.lasthost : "(¤£¸Ô)")); - prints("¡m¤¤l´Ñ¾ÔÁZ¡n%3d ³Ó %3d ±Ñ %3d ©M " - "¡m¶H´Ñ¾ÔÁZ¡n%3d ³Ó %3d ±Ñ %3d ©M\n", - muser.five_win, muser.five_lose, muser.five_tie, - muser.chc_win, muser.chc_lose, muser.chc_tie); -#ifdef ASSESS - prints("¡mÄv¼Ðµû¤ñ¡n Àu %d / ¦H %d", muser.goodsale, muser.badsale); - move(6, 40); -#endif - if ((uentp && ((fri_stat & HFM) || strcmp(muser.userid,cuser.userid) == 0) && !uentp->invisible)) - prints("¡m ©Ê §O ¡n%-28.28s\n", sex[muser.sex % 8]); - - showplans_userec(&muser); - if(HasUserPerm(PERM_SYSOP|PERM_POLICE) ) - { - if(vmsg("T: ¶}¥ß»@³æ")=='T') - violate_law(&muser, tuid); - } - else - pressanykey(); - if(now-last_query<1) - sleep(2); - else if(now-last_query<2) - sleep(1); - last_query=now; - return FULLUPDATE; - } - return DONOTHING; -} - -static char t_last_write[80]; - -void check_water_init(void) -{ - if(water==NULL) { - water = (water_t*)malloc(sizeof(water_t)*6); - memset(water, 0, sizeof(water_t)*6); - water_which = &water[0]; - - strlcpy(water[0].userid, " ¥þ³¡ ", sizeof(water[0].userid)); - } -} - -static void -water_scr(const water_t * tw, int which, char type) -{ - if (type == 1) { - int i; - const int colors[] = {33, 37, 33, 37, 33}; - move(8 + which, 28); - outc(' '); - move(8 + which, 28); - prints(ANSI_COLOR(1;37;45) " %c %-14s " ANSI_COLOR(0) "", - tw->uin ? ' ' : 'x', - tw->userid); - for (i = 0; i < 5; ++i) { - move(16 + i, 4); - outc(' '); - move(16 + i, 4); - if (tw->msg[(tw->top - i + 4) % 5].last_call_in[0] != 0) - prints(ANSI_COLOR(0) " " ANSI_COLOR(1;%d;44) "¡¹%-64s" ANSI_COLOR(0) " \n", - colors[i], - tw->msg[(tw->top - i + 4) % 5].last_call_in); - else - outs(ANSI_COLOR(0) "¡@\n"); - } - - move(21, 4); - outc(' '); - move(21, 4); - prints(ANSI_COLOR(0) " " ANSI_COLOR(1;37;46) "%-66s" ANSI_COLOR(0) " \n", - tw->msg[5].last_call_in); - - move(0, 0); - outc(' '); - move(0, 0); -#ifdef PLAY_ANGEL - if (tw->msg[0].msgmode == MSGMODE_TOANGEL) - outs(ANSI_COLOR(0) "¦^µª¤p¥D¤H:"); - else -#endif - prints(ANSI_COLOR(0) "¤ÏÀ» %s:", tw->userid); - clrtoeol(); - move(0, strlen(tw->userid) + 6); - } else { - -#ifndef USE_PFTERM - // workaround poor terminal, made by in2. - move(8 + which, 28); - outs("123456789012345678901234567890"); -#endif // !USE_PFTERM - - move(8 + which, 28); - prints(ANSI_COLOR(1;37;44) " %c %-13s¡@" ANSI_COLOR(0) "", - tw->uin ? ' ' : 'x', - tw->userid); - } -} - -void -my_write2(void) -{ - int i, ch, currstat0; - char genbuf[256], msg[80], done = 0, c0, which; - water_t *tw; - unsigned char mode0; - - check_water_init(); - if (swater[0] == NULL) - return; - wmofo = REPLYING; - currstat0 = currstat; - c0 = currutmp->chatid[0]; - mode0 = currutmp->mode; - currutmp->mode = 0; - currutmp->chatid[0] = 3; - currstat = DBACK; - - //init screen - move(WB_OFO_USER_TOP, WB_OFO_USER_LEFT); - outs(ANSI_COLOR(1;33;46) " ¡ô ¤ô²y¤ÏÀ»¹ï¶H ¡õ" ANSI_COLOR(0) ""); - for (i = 0; i < WB_OFO_USER_HEIGHT;++i) - if (swater[i] == NULL || swater[i]->pid == 0) - break; - else { - if (swater[i]->uin && - (swater[i]->pid != swater[i]->uin->pid || - swater[i]->userid[0] != swater[i]->uin->userid[0])) - swater[i]->uin = search_ulist_pid(swater[i]->pid); - water_scr(swater[i], i, 0); - } - move(WB_OFO_MSG_TOP, WB_OFO_MSG_LEFT); - outs(ANSI_COLOR(0) " " ANSI_COLOR(1;35) "¡º" ANSI_COLOR(1;36) "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" - "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" ANSI_COLOR(1;35) "¡º" ANSI_COLOR(0) " "); - move(WB_OFO_MSG_BOTTOM, WB_OFO_MSG_LEFT); - outs(" " ANSI_COLOR(1;35) "¡º" ANSI_COLOR(1;36) "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" - "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" ANSI_COLOR(1;35) "¡º" ANSI_COLOR(0) " "); - water_scr(swater[0], 0, 1); - refresh(); - - which = 0; - do { - switch ((ch = igetch())) { - case Ctrl('T'): - case KEY_UP: - if (water_usies != 1) { - water_scr(swater[(int)which], which, 0); - which = (which - 1 + water_usies) % water_usies; - water_scr(swater[(int)which], which, 1); - refresh(); - } - break; - - case KEY_DOWN: - case Ctrl('R'): - if (water_usies != 1) { - water_scr(swater[(int)which], which, 0); - which = (which + 1 + water_usies) % water_usies; - water_scr(swater[(int)which], which, 1); - refresh(); - } - break; - - case KEY_LEFT: - done = 1; - break; - - case KEY_UNKNOWN: - break; - - default: - done = 1; - tw = swater[(int)which]; - - if (!tw->uin) - break; - - if (ch != '\r' && ch != '\n') { - msg[0] = ch, msg[1] = 0; - } else - msg[0] = 0; - move(0, 0); - outs(ANSI_RESET); - 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, "¦^µª¤p¥D¤H:"); - i = WATERBALL_CONFIRM_ANSWER; - } else { /* tw->msg[0].msgmode == MSGMODE_FROMANGEL */ - strcpy(genbuf, "¦A°Ý¥L¤@¦¸¡G"); - i = WATERBALL_CONFIRM_ANGEL; - } -#endif - if (!oldgetdata(0, 0, genbuf, msg, - 80 - strlen(tw->userid) - 6, DOECHO)) - break; - - if (my_write(tw->pid, msg, tw->userid, i, tw->uin)) - strlcpy(tw->msg[5].last_call_in, t_last_write, - sizeof(tw->msg[5].last_call_in)); - break; - } - } while (!done); - - currstat = currstat0; - currutmp->chatid[0] = c0; - currutmp->mode = mode0; - if (wmofo == RECVINREPLYING) { - wmofo = NOTREPLYING; - write_request(0); - } - wmofo = NOTREPLYING; -} - -/* - * ³Q©I¥sªº®É¾÷: - * 1. ¥á¸s²Õ¤ô²y flag = WATERBALL_PREEDIT, 1 (pre-edit) - * 2. ¦^¤ô²y flag = WATERBALL_GENERAL, 0 - * 3. ¤W¯¸aloha flag = WATERBALL_ALOHA, 2 (pre-edit) - * 4. ¼s¼½ flag = WATERBALL_SYSOP, 3 if SYSOP - * flag = WATERBALL_PREEDIT, 1 otherwise - * 5. ¥á¤ô²y flag = WATERBALL_GENERAL, 0 - * 6. my_write2 flag = WATERBALL_CONFIRM, 4 (pre-edit but confirm) - * 7. (when defined PLAY_ANGEL) - * ©I¥s¤p¤Ñ¨Ï flag = WATERBALL_ANGEL, 5 (id = "¤p¤Ñ¨Ï") - * 8. (when defined PLAY_ANGEL) - * ¦^µª¤p¥D¤H flag = WATERBALL_ANSWER, 6 (ÁôÂà id) - * 9. (when defined PLAY_ANGEL) - * ©I¥s¤p¤Ñ¨Ï flag = WATERBALL_CONFIRM_ANGEL, 7 (pre-edit) - * 10. (when defined PLAY_ANGEL) - * ¦^µª¤p¥D¤H flag = WATERBALL_CONFIRM_ANSWER, 8 (pre-edit) - */ -int -my_write(pid_t pid, const char *prompt, const char *id, int flag, userinfo_t * puin) -{ - int len, currstat0 = currstat, fri_stat = -1; - char msg[80], destid[IDLEN + 1]; - char genbuf[200], buf[200], c0 = currutmp->chatid[0]; - unsigned char mode0 = currutmp->mode; - userinfo_t *uin; - uin = (puin != NULL) ? puin : (userinfo_t *) search_ulist_pid(pid); - strlcpy(destid, id, sizeof(destid)); - check_water_init(); - - /* what if uin is NULL but other conditions are not true? - * will this situation cause SEGV? - * should this "!uin &&" replaced by "!uin ||" ? - */ - if ((!uin || !uin->userid[0]) && !((flag == WATERBALL_GENERAL -#ifdef PLAY_ANGEL - || flag == WATERBALL_ANGEL || flag == WATERBALL_ANSWER -#endif - ) - && water_which->count > 0)) { - vmsg("ÁV¿|! ¹ï¤è¤w¸¨¶]¤F(¤£¦b¯¸¤W)! "); - watermode = -1; - return 0; - } - currutmp->mode = 0; - currutmp->chatid[0] = 3; - currstat = DBACK; - - if (flag == WATERBALL_GENERAL -#ifdef PLAY_ANGEL - || flag == WATERBALL_ANGEL || flag == WATERBALL_ANSWER -#endif - ) { - /* ¤@¯ë¤ô²y */ - watermode = 0; - - /* should we alert if we're in disabled mode? */ - switch(currutmp->pager) - { - case PAGER_DISABLE: - case PAGER_ANTIWB: - move(1, 0); clrtoeol(); - outs(ANSI_COLOR(1;31) "§Aªº©I¥s¾¹¥Ø«e¤£±µ¨ü§O¤H¥á¤ô²y¡A¹ï¤è¥i¯àµLªk¦^¸Ü¡C" ANSI_RESET); - break; - - case PAGER_FRIENDONLY: -#if 0 - // ¦pªG¹ï¤è¥¿¦b¤U¯¸¡A³oÓ¦n¹³¤£¤Ó÷| crash (?) */ - if (uin && uin->userid[0]) - { - fri_stat = friend_stat(currutmp, uin); - if(fri_stat & HFM) - break; - } -#endif - move(1, 0); clrtoeol(); - outs(ANSI_COLOR(1;31) "§Aªº©I¥s¾¹¥Ø«e¥u±µ¨ü¦n¤Í¥á¤ô²y¡AY¹ï¤è«D¦n¤Í«h¥i¯àµLªk¦^¸Ü¡C" ANSI_RESET); - break; - } - - if (!(len = getdata(0, 0, prompt, msg, 56, DOECHO))) { - currutmp->chatid[0] = c0; - currutmp->mode = mode0; - currstat = currstat0; - watermode = -1; - return 0; - } - - if (watermode > 0) { - int i; - - i = (water_which->top - watermode + MAX_REVIEW) % MAX_REVIEW; - uin = (userinfo_t *) search_ulist_pid(water_which->msg[i].pid); -#ifdef PLAY_ANGEL - if (water_which->msg[i].msgmode == MSGMODE_FROMANGEL) - flag = WATERBALL_ANGEL; - else if (water_which->msg[i].msgmode == MSGMODE_TOANGEL) - flag = WATERBALL_ANSWER; - else - flag = WATERBALL_GENERAL; -#endif - strlcpy(destid, water_which->msg[i].userid, sizeof(destid)); - } - } else { - /* pre-edit ªº¤ô²y */ - strlcpy(msg, prompt, sizeof(msg)); - len = strlen(msg); - } - - strip_ansi(msg, msg, STRIP_ALL); - if (uin && *uin->userid && - (flag == WATERBALL_GENERAL || flag == WATERBALL_CONFIRM -#ifdef PLAY_ANGEL - || flag == WATERBALL_ANGEL || flag == WATERBALL_ANSWER - || flag == WATERBALL_CONFIRM_ANGEL - || flag == WATERBALL_CONFIRM_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; - currutmp->mode = mode0; - currstat = currstat0; - watermode = -1; - return 0; - } - } - watermode = -1; - if (!uin || !*uin->userid || (strcasecmp(destid, uin->userid) -#ifdef PLAY_ANGEL - && flag != WATERBALL_ANGEL && flag != WATERBALL_CONFIRM_ANGEL) || - ((flag == WATERBALL_ANGEL || flag == WATERBALL_CONFIRM_ANGEL) - && strcasecmp(cuser.myangel, uin->userid) -#endif - )) { - vmsg("ÁV¿|! ¹ï¤è¤w¸¨¶]¤F(¤£¦b¯¸¤W)! "); - currutmp->chatid[0] = c0; - currutmp->mode = mode0; - currstat = currstat0; - return 0; - } - if(fri_stat < 0) - fri_stat = friend_stat(currutmp, uin); - // else, fri_stat was already calculated. */ - - if (flag != WATERBALL_ALOHA) { /* aloha ªº¤ô²y¤£¥Î¦s¤U¨Ó */ - /* ¦s¨ì¦Û¤vªº¤ô²yÀÉ */ - if (!fp_writelog) { - sethomefile(genbuf, cuser.userid, fn_writelog); - fp_writelog = fopen(genbuf, "a"); - } - if (fp_writelog) { - fprintf(fp_writelog, "To %s: %s [%s]\n", - destid, msg, Cdatelite(&now)); - snprintf(t_last_write, 66, "To %s: %s", destid, msg); - } - } - 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 != 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 - !HasUserPerm(PERM_SYSOP) && - (uin->pager == PAGER_ANTIWB || - uin->pager == PAGER_DISABLE || - (uin->pager == PAGER_FRIENDONLY && - !(fri_stat & HFM)))) -#ifdef PLAY_ANGEL - || ((flag == WATERBALL_ANGEL || flag == WATERBALL_CONFIRM_ANGEL) - && he_reject_me(uin)) -#endif - ) { - outmsg(ANSI_COLOR(1;33;41) "ÁV¿|! ¹ï¤è¨¾¤ô¤F! " ANSI_COLOR(37) "~>_<~" ANSI_RESET); - } else { - int write_pos = uin->msgcount; /* try to avoid race */ - if ( write_pos < (MAX_MSGS - 1) ) { /* race here */ - unsigned char pager0 = uin->pager; - - uin->msgcount = write_pos + 1; - uin->pager = PAGER_DISABLE; - uin->msgs[write_pos].pid = currpid; -#ifdef PLAY_ANGEL - if (flag == WATERBALL_ANSWER || flag == WATERBALL_CONFIRM_ANSWER) - strlcpy(uin->msgs[write_pos].userid, "¤p¤Ñ¨Ï", - 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 != WATERBALL_ALOHA) - outmsg(ANSI_COLOR(1;33;41) "ÁV¿|! ¹ï¤è¤£¦æ¤F! (¦¬¨ì¤Ó¦h¤ô²y) " ANSI_COLOR(37) "@_@" ANSI_RESET); - - if (uin->msgcount >= 1 && -#ifdef NOKILLWATERBALL - !(uin->wbtime = now) /* race */ -#else - (uin->pid <= 0 || kill(uin->pid, SIGUSR2) == -1) -#endif - && flag != WATERBALL_ALOHA) - outmsg(ANSI_COLOR(1;33;41) "ÁV¿|! ¨S¥´¤¤! " ANSI_COLOR(37) "~>_<~" ANSI_RESET); - else if (uin->msgcount == 1 && flag != WATERBALL_ALOHA) - outmsg(ANSI_COLOR(1;33;44) "¤ô²y¯{¹L¥h¤F! " ANSI_COLOR(37) "*^o^*" ANSI_RESET); - else if (uin->msgcount > 1 && uin->msgcount < MAX_MSGS && - flag != WATERBALL_ALOHA) - outmsg(ANSI_COLOR(1;33;44) "¦A¸É¤W¤@²É! " ANSI_COLOR(37) "*^o^*" ANSI_RESET); - -#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(); - - currutmp->chatid[0] = c0; - currutmp->mode = mode0; - currstat = currstat0; - return 1; -} - -void -getmessage(msgque_t msg) -{ - int write_pos = currutmp->msgcount; - if ( write_pos < (MAX_MSGS - 1) ) { - unsigned char pager0 = currutmp->pager; - currutmp->msgcount = write_pos+1; - memcpy(&currutmp->msgs[write_pos], &msg, sizeof(msgque_t)); - currutmp->pager = pager0; - write_request(SIGUSR1); - } -} - -void -t_display_new(void) -{ - static int t_display_new_flag = 0; - int i, off = 2; - if (t_display_new_flag) - return; - else - t_display_new_flag = 1; - - check_water_init(); - if (WATERMODE(WATER_ORIG)) - water_which = &water[0]; - else - off = 3; - - if (water[0].count && watermode > 0) { - move(1, 0); - outs("¢w¢w¢w¢w¢w¢w¢w¤ô¢w²y¢w¦^¢wÅU¢w¢w¢w"); - outs(WATERMODE(WATER_ORIG) ? - "¢w¢w¢w¢w¢w¢w¥Î[Ctrl-R Ctrl-T]Áä¤Á´«¢w¢w¢w¢w¢w" : - "¥Î[Ctrl-R Ctrl-T Ctrl-F Ctrl-G ]Áä¤Á´«¢w¢w¢w¢w"); - if (WATERMODE(WATER_NEW)) { - move(2, 0); - clrtoeol(); - for (i = 0; i < 6; i++) { - if (i > 0) - if (swater[i - 1]) { - - if (swater[i - 1]->uin && - (swater[i - 1]->pid != swater[i - 1]->uin->pid || - swater[i - 1]->userid[0] != swater[i - 1]->uin->userid[0])) - swater[i - 1]->uin = (userinfo_t *) search_ulist_pid(swater[i - 1]->pid); - prints("%s%c%-13.13s" ANSI_RESET, - swater[i - 1] != water_which ? "" : - swater[i - 1]->uin ? ANSI_COLOR(1;33;47) : - ANSI_COLOR(1;33;45), - !swater[i - 1]->uin ? '#' : ' ', - swater[i - 1]->userid); - } else - outs(" "); - else - prints("%s ¥þ³¡ " ANSI_RESET, - water_which == &water[0] ? ANSI_COLOR(1;33;47) " " : - " " - ); - } - } - for (i = 0; i < water_which->count; i++) { - 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; - - move(i + (WATERMODE(WATER_ORIG) ? 2 : 3), 0); - clrtoeol(); - if (watermode - 1 != i) - prints(ANSI_COLOR(1;33;46) " %s " ANSI_COLOR(37;45) " %s " ANSI_RESET "%*s", - water_which->msg[a].userid, - water_which->msg[a].last_call_in, len, - ""); - else - prints(ANSI_COLOR(1;44) ">" ANSI_COLOR(1;33;47) "%s " - ANSI_COLOR(37;45) " %s " ANSI_RESET "%*s", - water_which->msg[a].userid, - water_which->msg[a].last_call_in, - len, ""); - } - - if (t_last_write[0]) { - move(i + off, 0); - clrtoeol(); - outs(t_last_write); - i++; - } - move(i + off, 0); - outs("¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" - "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w"); - if (WATERMODE(WATER_NEW)) - while (i++ <= water[0].count) { - move(i + off, 0); - clrtoeol(); - } - } - t_display_new_flag = 0; -} - -int -t_display(void) -{ - char genbuf[200], ans[4]; - if (fp_writelog) { - fclose(fp_writelog); - fp_writelog = NULL; - } - setuserfile(genbuf, fn_writelog); - if (more(genbuf, YEA) != -1) { - grayout(0, b_lines-5, GRAYOUT_DARK); - move(b_lines - 4, 0); - clrtobot(); - outs(ANSI_COLOR(1;33;45) "¡¹¤ô²y¾ã²zµ{¦¡ " ANSI_RESET "\n" - "´£¿ô±z: ¥i±N¤ô²y¦s¤J«H½c(M)«á, ¨ì¡i¶l¥ó¿ï³æ¡j¸Ó«H¥ó«e«ö u,\n" - "¨t²Î·|±N¤ô²y¬ö¿ý«·s¾ã²z«á±H°eµ¹±zò! " ANSI_RESET "\n"); - - getdata(b_lines - 1, 0, "²M°£(C) ¦s¤J«H½c(M) «O¯d(R) (C/M/R)?[R]", - ans, sizeof(ans), LCECHO); - if (*ans == 'm') { - fileheader_t mymail; - char title[128], buf[80]; - - sethomepath(buf, cuser.userid); - stampfile(buf, &mymail); - - mymail.filemode = FILE_READ ; - strlcpy(mymail.owner, "[³Æ.§Ñ.¿ý]", sizeof(mymail.owner)); - strlcpy(mymail.title, "¼ö½u°O¿ý", sizeof(mymail.title)); - sethomedir(title, cuser.userid); - Rename(genbuf, buf); - append_record(title, &mymail, sizeof(mymail)); - } else if (*ans == 'c') - unlink(genbuf); - return FULLUPDATE; - } - return DONOTHING; -} - -static void -do_talk_nextline(talkwin_t * twin) -{ - twin->curcol = 0; - if (twin->curln < twin->eline) - ++(twin->curln); - else - { - int i, iend = twin->eline - twin->sline; - region_scroll_up(twin->sline, twin->eline); - // also scroll up our buffer - for (i = 0; i < iend; i++) - { - memcpy(&twin->big_picture[i], &twin->big_picture[i+1], - sizeof(twpic_t)); - } - // zero last line - memset(&twin->big_picture[iend], 0, sizeof(twpic_t)); - } - move(twin->curln, twin->curcol); -} - -static int -iscompletedbcs(const unsigned char* str) -{ - int isdbcs = 0; - while (*str) - { - if (isdbcs == 1) isdbcs = 2; - else if ((unsigned char)*str > 0x80) isdbcs = 1; - else isdbcs = 0; - str++; - } - - return (isdbcs == 1) ? 0 : 1; -} - -static void -talk_refreshline(talkwin_t *twin) -{ - // dirty screen - twpic_t *line = twin->big_picture + (twin->curln - twin->sline); - int iscomplete = iscompletedbcs(line->data); - int len = strlen((char*)line->data); - - move(twin->curln, 0); - clrtoeol(); - if (!iscomplete) len--; - outs_n((char*)line->data, len); - if (!iscomplete) outc('?'); - move(twin->curln, twin->curcol); -} - -static void -do_talk_char(talkwin_t * twin, int ch, FILE *flog) -{ - twpic_t *line; - char buf[TALK_BUFLEN] = ""; - - line = twin->big_picture+(twin->curln - twin->sline); - - if (isprint2(ch)) { - - - if (line->len < TALK_MAXCOL) - move(twin->curln, twin->curcol); - else - do_talk_nextline(twin); - - // do_talk_nextline may change current line - line = twin->big_picture + (twin->curln -twin->sline); - memmove(line->data + twin->curcol+1, line->data + twin->curcol, - line->len - twin->curcol +1); - line->data[twin->curcol++] = ch; - line->data[++line->len] = 0; - - // dirty screen - talk_refreshline(twin); - - if (line->len < TALK_MAXCOL) - return; - - // max buffer, log it. - strlcpy(buf, (char *)line->data, line->len + 1); - - } else switch (ch) { - - case Ctrl('G'): - bell(); - return; - - case Ctrl('A'): - twin->curcol = 0; - move(twin->curln, twin->curcol); - return; - case Ctrl('E'): - twin->curcol = line->len; - move(twin->curln, twin->curcol); - return; - - - case Ctrl('K'): - line->len = twin->curcol; - memset(line->data+line->len, 0, TALK_MAXCOL - line->len); - move(twin->curln, twin->curcol); - clrtoeol(); - return; - case Ctrl('Y'): - twin->curcol = 0; - line->len = 0; - memset(line->data, 0, TALK_MAXCOL); - move(twin->curln, twin->curcol); - clrtoeol(); - return; - - case Ctrl('M'): - case Ctrl('J'): - strlcpy(buf, (char *)line->data, line->len + 1); - buf[line->len] = 0; - do_talk_nextline(twin); - break; - - case Ctrl('B'): - if (twin->curcol > 0) { - --(twin->curcol); -#ifdef DBCSAWARE - if(twin->curcol > 0 && twin->curcol < line->len && ISDBCSAWARE()) - { - if(getDBCSstatus(line->data, twin->curcol) == DBCS_TRAILING) - twin->curcol --; - } -#endif - move(twin->curln, twin->curcol); - } - return; - - case Ctrl('F'): - if (twin->curcol < line->len) { - ++(twin->curcol); -#ifdef DBCSAWARE - if(twin->curcol < TALK_MAXCOL && twin->curcol < line->len && ISDBCSAWARE()) - { - if(getDBCSstatus(line->data, twin->curcol) == DBCS_TRAILING) - twin->curcol++; - } -#endif - move(twin->curln, twin->curcol); - } - return; - - - case Ctrl('P'): - strlcpy(buf, (char *)line->data, line->len + 1); - if (twin->curln > twin->sline) { - --twin->curln; - line = twin->big_picture + (twin->curln -twin->sline); - } - if (twin->curcol > line->len) - twin->curcol = line->len; - -#ifdef DBCSAWARE - // curln may be changed. - if(twin->curcol > 0 && twin->curcol < line->len && - getDBCSstatus(line->data, twin->curcol) == DBCS_TRAILING) - twin->curcol--; -#endif - move(twin->curln, twin->curcol); - // XXX break here (for log)? - break; - - case Ctrl('N'): - strlcpy(buf, (char *)line->data, line->len + 1); - if (twin->curln < twin->eline) { - ++twin->curln; - line = twin->big_picture + (twin->curln -twin->sline); - } - if (twin->curcol > line->len) - twin->curcol = line->len; - -#ifdef DBCSAWARE - // curln may be changed. - line = twin->big_picture + (twin->curln -twin->sline); - if(twin->curcol > 0 && twin->curcol < line->len && - getDBCSstatus(line->data, twin->curcol) == DBCS_TRAILING) - twin->curcol--; -#endif - move(twin->curln, twin->curcol); - // XXX break here (for log)? - break; - - // complex data change - case Ctrl('H'): - case '\177': - if (twin->curcol > 0) - { - int delta = 1; - -#ifdef DBCSAWARE - if (twin->curcol > 1 && ISDBCSAWARE() && - getDBCSstatus(line->data, twin->curcol-1) == DBCS_TRAILING) - delta++; -#endif - memmove(line->data + twin->curcol-delta, line->data + twin->curcol, - line->len - twin->curcol +1); - line->len -= delta; - twin->curcol -= delta; - // dirty screen - talk_refreshline(twin); - } - return; - - case Ctrl('D'): - if (twin->curcol < line->len) - { - int delta = 1; - -#ifdef DBCSAWARE - if (ISDBCSAWARE() && - getDBCSstatus(line->data, twin->curcol) == DBCS_LEADING) - delta++; -#endif - memmove(line->data + twin->curcol, line->data + twin->curcol+delta, - line->len - twin->curcol -delta+1); - line->len -= delta; - memset(line->data + line->len, 0, TALK_MAXCOL - line->len); - // dirty screen - talk_refreshline(twin); - } - return; - } - - trim(buf); - if (*buf) - fprintf(flog, "%s%s: %s%s\n", - (twin->eline == b_lines - 1) ? ANSI_COLOR(1;35) : "", - (twin->eline == b_lines - 1) ? - getuserid(currutmp->destuid) : cuser.userid, buf, - (ch == Ctrl('P')) ? ANSI_COLOR(37;45) "(Up)" ANSI_RESET : ANSI_RESET); -} - -static void -do_talk(int fd) -{ - struct talkwin_t mywin, itswin; - char mid_line[128], data[200]; - int i, datac, ch; - int im_leaving = 0; - FILE *log, *flog; - struct tm *ptime; - char genbuf[200], fpath[100]; - - STATINC(STAT_DOTALK); - ptime = localtime4(&now); - - setuserfile(fpath, "talk_XXXXXX"); - flog = fdopen(mkstemp(fpath), "w"); - - setuserfile(genbuf, fn_talklog); - - if ((log = fopen(genbuf, "w"))) - fprintf(log, "[%d/%d %d:%02d] & %s\n", - ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, - ptime->tm_min, save_page_requestor); - setutmpmode(TALK); - - ch = 58 - strlen(save_page_requestor); - snprintf(genbuf, sizeof(genbuf), "%s¡i%s", cuser.userid, cuser.nickname); - i = ch - strlen(genbuf); - if (i >= 0) - i = (i >> 1) + 1; - else { - genbuf[ch] = '\0'; - i = 1; - } - memset(data, ' ', i); - data[i] = '\0'; - - snprintf(mid_line, sizeof(mid_line), - ANSI_COLOR(1;46;37) " ½Í¤Ñ»¡¦a " ANSI_COLOR(45) "%s%s¡j" - " »P %s%s" ANSI_COLOR(0) "", - data, genbuf, save_page_requestor, data); - - memset(&mywin, 0, sizeof(mywin)); - memset(&itswin, 0, sizeof(itswin)); - - i = b_lines >> 1; - mywin.eline = i - 1; - itswin.curln = itswin.sline = i + 1; - itswin.eline = b_lines - 1; - - // memory allocation - mywin.big_picture = (twpic_t*) malloc ( - sizeof(twpic_t) * (mywin.eline - mywin.sline +1)); - itswin.big_picture = (twpic_t*) malloc ( - sizeof(twpic_t) * (itswin.eline- itswin.sline +1)); - - // reset buffer - for (i = mywin.sline; i <= mywin.eline; i++) - { - mywin.big_picture[i - mywin.sline].len = 0; - memset(mywin.big_picture[i-mywin.sline].data, 0, TALK_BUFLEN); - } - for (i = itswin.sline; i <= itswin.eline; i++) - { - itswin.big_picture[i - itswin.sline].len = 0; - memset(itswin.big_picture[i-itswin.sline].data, 0, TALK_BUFLEN); - } - - clear(); - move(mywin.eline+1, 0); - outs(mid_line); - move(0, 0); - - add_io(fd, 0); - - while (1) { - ch = igetch(); - if (ch == I_OTHERDATA) { - // getyx(&y, &x); - datac = recv(fd, data, sizeof(data), 0); - if (datac <= 0) - break; - for (i = 0; i < datac; i++) - do_talk_char(&itswin, data[i], flog); - // move(y, x); - } else if (ch == KEY_UNKNOWN) { - // skip - } else { - if (ch == Ctrl('C')) { - if (im_leaving) - break; - move(b_lines, 0); - clrtoeol(); - outs("¦A«ö¤@¦¸ Ctrl-C ´N¥¿¦¡¤¤¤î½Í¸ÜÅo¡I"); - im_leaving = 1; - continue; - } - if (im_leaving) { - move(b_lines, 0); - clrtoeol(); - im_leaving = 0; - } - switch (ch) { - case KEY_LEFT: /* §â2byteªºÁä§ï¬°¤@byte */ - ch = Ctrl('B'); - break; - case KEY_RIGHT: - ch = Ctrl('F'); - break; - case KEY_UP: - ch = Ctrl('P'); - break; - case KEY_DOWN: - ch = Ctrl('N'); - break; - } - data[0] = (char)ch; - if (send(fd, data, 1, 0) != 1) - break; - if (log) - fputc((ch == Ctrl('M')) ? '\n' : (char)*data, log); - do_talk_char(&mywin, *data, flog); - } - } - if (log) - fclose(log); - - add_io(0, 0); - close(fd); - - if (flog) { - char ans[4]; - int i; - - fprintf(flog, "\n" ANSI_COLOR(33;44) "Â÷§Oµe± [%s] ... " ANSI_RESET "\n", - Cdatelite(&now)); - - fprintf(flog, "[%s]:\n", cuser.userid); - for (i = 0; i < mywin.eline - mywin.sline +1; i++) - if (mywin.big_picture[i].len) - fprintf(flog, "%.*s\n", mywin.big_picture[i].len, mywin.big_picture[i].data); - - fprintf(flog, "[%s]:\n", getuserid(currutmp->destuid)); - for (i = 0; i < itswin.eline - itswin.sline +1; i++) - if (itswin.big_picture[i].len) - fprintf(flog, "%.*s\n", itswin.big_picture[i].len, itswin.big_picture[i].data); - - fclose(flog); - redrawwin(); - more(fpath, NA); - - // force user decide how to deal with the log - while (1) { - getdata(b_lines - 1, 0, "²M°£(C) ²¾¦Ü³Æ§Ñ¿ý(M). (c/m)? ", - ans, sizeof(ans), LCECHO); - if (ans[0] == 'c' || ans[0] == 'm') - break; - move(b_lines-2, 0); - prints(ANSI_COLOR(0;1;3%d) "½Ð¥¿½T¿é¤J c ©Î m ªº«ü¥O¡C" ANSI_RESET, - (now % 7)+1); - if (ans[0] == 0) outs("¬°ÁקK»~«ö©Ò¥H¥u ENTER ¬O¤£¦æªº¡C"); - } - - if (*ans == 'm') { - fileheader_t mymail; - char title[128]; - - sethomepath(genbuf, cuser.userid); - stampfile(genbuf, &mymail); - mymail.filemode = FILE_READ ; - strlcpy(mymail.owner, "[³Æ.§Ñ.¿ý]", sizeof(mymail.owner)); - snprintf(mymail.title, sizeof(mymail.title), - "¹ï¸Ü°O¿ý " ANSI_COLOR(1;36) "(%s)" ANSI_RESET, - getuserid(currutmp->destuid)); - sethomedir(title, cuser.userid); - Rename(fpath, genbuf); - append_record(title, &mymail, sizeof(mymail)); - } else - unlink(fpath); - flog = 0; - } - - // free memory - free(mywin.big_picture); - free(itswin.big_picture); - setutmpmode(XINFO); - redrawwin(); -} - -#define lockreturn(unmode, state) if(lockutmpmode(unmode, state)) return - -int make_connection_to_somebody(userinfo_t *uin, int timeout){ - int sock, length, pid, ch; - struct sockaddr_in server; - - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) { - perror("sock err"); - unlockutmpmode(); - return -1; - } - server.sin_family = PF_INET; - server.sin_addr.s_addr = INADDR_ANY; - server.sin_port = 0; - if (bind(sock, (struct sockaddr *) & server, sizeof(server)) < 0) { - close(sock); - perror("bind err"); - unlockutmpmode(); - return -1; - } - length = sizeof(server); -#if defined(Solaris) && __OS_MAJOR_VERSION__ == 5 && __OS_MINOR_VERSION__ < 7 - if (getsockname(sock, (struct sockaddr *) & server, & length) < 0) { -#else - if (getsockname(sock, (struct sockaddr *) & server, (socklen_t *) & length) < 0) { -#endif - close(sock); - perror("sock name err"); - unlockutmpmode(); - return -1; - } - currutmp->sockactive = YEA; - currutmp->sockaddr = server.sin_port; - currutmp->destuid = uin->uid; - setutmpmode(PAGE); - uin->destuip = currutmp - &SHM->uinfo[0]; - pid = uin->pid; - if (pid > 0) - kill(pid, SIGUSR1); - clear(); - prints("¥¿©I¥s %s.....\nÁä¤J Ctrl-D ¤¤¤î....", uin->userid); - - if(listen(sock, 1)<0) { - close(sock); - return -1; - } - add_io(sock, timeout); - - while (1) { - ch = igetch(); - if (ch == I_TIMEOUT) { - ch = uin->mode; - if (!ch && uin->chatid[0] == 1 && - uin->destuip == currutmp - &SHM->uinfo[0]) { - bell(); - outmsg("¹ï¤è¦^À³¤¤..."); - refresh(); - } else if (ch == EDITING || ch == TALK || ch == CHATING || - ch == PAGE || ch == MAILALL || ch == MONITOR || - ch == M_FIVE || ch == CHC || - (!ch && (uin->chatid[0] == 1 || - uin->chatid[0] == 3))) { - add_io(0, 0); - close(sock); - currutmp->sockactive = currutmp->destuid = 0; - vmsg("¤H®a¦b¦£°Õ"); - unlockutmpmode(); - return -1; - } else { - // change to longer timeout - add_io(sock, 20); - move(0, 0); - outs("¦A"); - bell(); - - uin->destuip = currutmp - &SHM->uinfo[0]; - if (pid <= 0 || kill(pid, SIGUSR1) == -1) { - close(sock); - currutmp->sockactive = currutmp->destuid = 0; - add_io(0, 0); - vmsg(msg_usr_left); - unlockutmpmode(); - return -1; - } - continue; - } - } - if (ch == I_OTHERDATA) - break; - - if (ch == '\004') { - add_io(0, 0); - close(sock); - currutmp->sockactive = currutmp->destuid = 0; - unlockutmpmode(); - return -1; - } - } - return sock; -} - -void -my_talk(userinfo_t * uin, int fri_stat, char defact) -{ - int sock, msgsock, ch; - pid_t pid; - char c; - char genbuf[4]; - unsigned char mode0 = currutmp->mode; - - genbuf[0] = defact; - ch = uin->mode; - strlcpy(currauthor, uin->userid, sizeof(currauthor)); - - if (ch == EDITING || ch == TALK || ch == CHATING || ch == PAGE || - ch == MAILALL || ch == MONITOR || ch == M_FIVE || ch == CHC || - ch == DARK || ch == UMODE_GO || ch == CHESSWATCHING || ch == REVERSI || - (!ch && (uin->chatid[0] == 1 || uin->chatid[0] == 3)) || - uin->lockmode == M_FIVE || uin->lockmode == CHC) { - if (ch == CHC || ch == M_FIVE || ch == UMODE_GO || - ch == CHESSWATCHING || ch == REVERSI) { - sock = make_connection_to_somebody(uin, 20); - if (sock < 0) - vmsg("µLªk«Ø¥ß³s½u"); - else { -#if defined(Solaris) && __OS_MAJOR_VERSION__ == 5 && __OS_MINOR_VERSION__ < 7 - msgsock = accept(sock, (struct sockaddr *) 0, 0); -#else - msgsock = accept(sock, (struct sockaddr *) 0, (socklen_t *) 0); -#endif - if (msgsock == -1) { - perror("accept"); - close(sock); - return; - } - close(sock); - strlcpy(currutmp->mateid, uin->userid, sizeof(currutmp->mateid)); - - switch (uin->sig) { - case SIG_CHC: - chc(msgsock, CHESS_MODE_WATCH); - break; - - case SIG_GOMO: - gomoku(msgsock, CHESS_MODE_WATCH); - break; - - case SIG_GO: - gochess(msgsock, CHESS_MODE_WATCH); - break; - - case SIG_REVERSI: - reversi(msgsock, CHESS_MODE_WATCH); - break; - } - } - } - else - outs("¤H®a¦b¦£°Õ"); - } else if (!HasUserPerm(PERM_SYSOP) && - (((fri_stat & HRM) && !(fri_stat & HFM)) || - ((!uin->pager) && !(fri_stat & HFM)))) { - outs("¹ï¤èÃö±¼©I¥s¾¹¤F"); - } else if (!HasUserPerm(PERM_SYSOP) && - (((fri_stat & HRM) && !(fri_stat & HFM)) || uin->pager == PAGER_DISABLE)) { - outs("¹ï¤è©Þ±¼©I¥s¾¹¤F"); - } else if (!HasUserPerm(PERM_SYSOP) && - !(fri_stat & HFM) && uin->pager == PAGER_FRIENDONLY) { - outs("¹ï¤è¥u±µ¨ü¦n¤Íªº©I¥s"); - } else if (!(pid = uin->pid) /* || (kill(pid, 0) == -1) */ ) { - //resetutmpent(); - outs(msg_usr_left); - } else { - int i,j; - - if (!defact) { - showplans(uin->userid); - move(2, 0); - for(i=0;i<2;i++) { - if(uin->withme & (WITHME_ALLFLAG<<i)) { - if(i==0) - outs("Åwªï¸ò§Ú¡G"); - else - outs("½Ð§O§ä§Ú¡G"); - for(j=0; j<32 && withme_str[j/2]; j+=2) - if(uin->withme & (1<<(j+i))) - if(withme_str[j/2]) { - outs(withme_str[j/2]); - outc(' '); - } - outc('\n'); - } - } - move(4, 0); - outs("n©M¥L(¦o) (T)½Í¤Ñ(F)¤U¤¤l´Ñ" -#ifdef USE_CHICKEN_PK - "(P)°«Ãdª«" -#endif // USE_CHICKEN_PK - "(C)¤U¶H´Ñ(D)¤U·t´Ñ(G)¤U³ò´Ñ(R)¤U¶Â¥Õ´Ñ"); - getdata(5, 0, " (N)¨S¨Æ§ä¿ù¤H¤F?[N] ", genbuf, 4, LCECHO); - } - - switch (*genbuf) { - case 'y': - case 't': - uin->sig = SIG_TALK; - break; - case 'f': - lockreturn(M_FIVE, LOCK_THIS); - uin->sig = SIG_GOMO; - break; - case 'c': - lockreturn(CHC, LOCK_THIS); - uin->sig = SIG_CHC; - break; - case 'd': - uin->sig = SIG_DARK; - break; - case 'g': - uin->sig = SIG_GO; - break; - case 'r': - uin->sig = SIG_REVERSI; - break; -#ifdef USE_CHICKEN_PK - case 'p': - { - userec_t xuser; - chicken_t xchk; - int error = 0; - - getuser(uin->userid, &xuser); - if (uin->lockmode == CHICKEN || currutmp->lockmode == CHICKEN) - error = 1; - else if (!load_chicken(cuser.userid, &xchk) || - !load_chicken(xuser.userid, &xchk)) - error = 2; - - if (error) { - vmsg(error == 2 ? "¨Ã«D¨â¤H³£¾iÃdª«" : - "¦³¤@¤èªºÃdª«¥¿¦b¨Ï¥Î¤¤"); - return; - } - uin->sig = SIG_PK; - } - break; -#endif // USE_CHICKEN_PK - default: - return; - } - - uin->turn = 1; - currutmp->turn = 0; - strlcpy(uin->mateid, currutmp->userid, sizeof(uin->mateid)); - strlcpy(currutmp->mateid, uin->userid, sizeof(currutmp->mateid)); - - sock = make_connection_to_somebody(uin, 5); - if(sock==-1) { - vmsg("µLªk«Ø¥ß³s½u"); - return; - } - -#if defined(Solaris) && __OS_MAJOR_VERSION__ == 5 && __OS_MINOR_VERSION__ < 7 - msgsock = accept(sock, (struct sockaddr *) 0, 0); -#else - msgsock = accept(sock, (struct sockaddr *) 0, (socklen_t *) 0); -#endif - if (msgsock == -1) { - perror("accept"); - close(sock); - unlockutmpmode(); - return; - } - add_io(0, 0); - close(sock); - currutmp->sockactive = NA; - - if (uin->sig == SIG_CHC || uin->sig == SIG_GOMO || - uin->sig == SIG_GO || uin->sig == SIG_REVERSI) - ChessEstablishRequest(msgsock); - - add_io(msgsock, 0); - while ((ch = igetch()) != I_OTHERDATA) { - if (ch == Ctrl('D')) { - add_io(0, 0); - close(msgsock); - unlockutmpmode(); - return; - } - } - - if (read(msgsock, &c, sizeof(c)) != sizeof(c)) - c = 'n'; - add_io(0, 0); - - if (c == 'y') { - snprintf(save_page_requestor, sizeof(save_page_requestor), - "%s (%s)", uin->userid, uin->nickname); - switch (uin->sig) { - case SIG_DARK: - main_dark(msgsock, uin); - break; -#ifdef USE_CHICKEN_PK - case SIG_PK: - chickenpk(msgsock); - break; -#endif - case SIG_GOMO: - gomoku(msgsock, CHESS_MODE_VERSUS); - break; - case SIG_CHC: - chc(msgsock, CHESS_MODE_VERSUS); - break; - case SIG_GO: - gochess(msgsock, CHESS_MODE_VERSUS); - break; - case SIG_REVERSI: - reversi(msgsock, CHESS_MODE_VERSUS); - break; - case SIG_TALK: - default: - do_talk(msgsock); - } - } else { - move(9, 9); - outs("¡i¦^µ¡j "); - switch (c) { - case 'a': - outs("§Ú²{¦b«Ü¦£¡A½Ðµ¥¤@·|¨à¦A call §Ú¡A¦n¶Ü¡H"); - break; - case 'b': - prints("¹ï¤£°_¡A§Ú¦³¨Æ±¡¤£¯à¸ò§A %s....", sig_des[uin->sig]); - break; - case 'd': - outs("§ÚnÂ÷¯¸Åo..¤U¦¸¦A²á§a.........."); - break; - case 'c': - outs("½Ð¤£n§n§Ú¦n¶Ü¡H"); - break; - case 'e': - outs("§ä§Ú¦³¨Æ¶Ü¡H½Ð¥ý¨Ó«Hò...."); - break; - case 'f': - { - char msgbuf[60]; - - read(msgsock, msgbuf, 60); - prints("¹ï¤£°_¡A§Ú²{¦b¤£¯à¸ò§A %s¡A¦]¬°\n", sig_des[uin->sig]); - move(10, 18); - outs(msgbuf); - } - break; - case '1': - prints("%s¡H¥ý®³100»È¨â¨Ó..", sig_des[uin->sig]); - break; - case '2': - prints("%s¡H¥ý®³1000»È¨â¨Ó..", sig_des[uin->sig]); - break; - default: - prints("§Ú²{¦b¤£·Q %s °Õ.....:)", sig_des[uin->sig]); - } - close(msgsock); - } - } - currutmp->mode = mode0; - currutmp->destuid = 0; - unlockutmpmode(); - pressanykey(); -} - -/* ¿ï³æ¦¡²á¤Ñ¤¶± */ -#define US_PICKUP 1234 -#define US_RESORT 1233 -#define US_ACTION 1232 -#define US_REDRAW 1231 - -static void -t_showhelp(void) -{ - clear(); - - outs(ANSI_COLOR(36) "¡i ¥ð¶¢²á¤Ñ¨Ï¥Î»¡©ú ¡j" ANSI_RESET "\n\n" - "(¡ö)(e) µ²§ôÂ÷¶} (h) ¬Ý¨Ï¥Î»¡©ú\n" - "(¡ô)/(¡õ)(n) ¤W¤U²¾°Ê (TAB) ¤Á´«±Æ§Ç¤è¦¡\n" - "(PgUp)(^B) ¤W¶¿ï³æ ( )(PgDn)(^F) ¤U¶¿ï³æ\n" - "(Hm)/($)(Ed) º/§À (S) ¨Ó·½/¦n¤Í´yz/¾ÔÁZ ¤Á´«\n" - "(m) ±H«H (q/c) ¬d¸ßºô¤Í/Ãdª«\n" - "(r) ¾\\Ū«H¥ó (l/C) ¬Ý¤W¦¸¼ö°T/¤Á´«Áô¨\n" - "(f) ¥þ³¡/¦n¤Í¦Cªí (¼Æ¦r) ¸õ¦Ü¸Ó¨Ï¥ÎªÌ\n" - "(p) ¤Á´«©I¥s¾¹ (g/i) µ¹¿ú/¤Á´«¤ß±¡\n" - "(a/d/o) ¦n¤Í ¼W¥[/§R°£/קï (s) ºô¤Í ID ·j´M\n" - "(N) קï¼ÊºÙ (y) §Ú·Q§ä¤H²á¤Ñ¡B¤U´Ñ¡K\n"); - - if (HasUserPerm(PERM_PAGE)) { - outs("\n" ANSI_COLOR(36) "¡i ¥æ½Í±M¥ÎÁä ¡j" ANSI_RESET "\n" - "(¡÷)(t)(Enter) ¸ò¥L¡þ¦o²á¤Ñ\n" - "(w) ¼ö½u Call in\n" - "(^W)¤Á´«¤ô²y¤è¦¡ ¤@¯ë / ¶i¶¥ / ¥¼¨Ó\n" - "(b) ¹ï¦n¤Í¼s¼½ (¤@©wn¦b¦n¤Í¦Cªí¤¤)\n" - "(^R) §Y®É¦^À³ (¦³¤H Call in §A®É)\n"); - } - if (HasUserPerm(PERM_SYSOP)) { - outs("\n" ANSI_COLOR(36) "¡i ¯¸ªø±M¥ÎÁä ¡j" ANSI_RESET "\n\n"); - outs("(u)/(H) ³]©w¨Ï¥ÎªÌ¸ê®Æ/¤Á´«Áô§Î¼Ò¦¡\n"); - outs("(K) §âÃa³J½ð¥X¥h\n"); -#if defined(SHOWBOARD) && defined(DEBUG) - outs("(Y) Åã¥Ü¥¿¦b¬Ý¤°»òªO\n"); -#endif - } -#ifdef PLAY_ANGEL - if (HasUserPerm(PERM_LOGINOK)) - pressanykey_or_callangel(); - else -#endif - pressanykey(); -} - -/* Kaede show friend description */ -static char * -friend_descript(const userinfo_t * uentp, char *desc_buf, int desc_buflen) -{ - char *space_buf = "", *flag; - char fpath[80], name[IDLEN + 2], *desc, *ptr; - int len; - FILE *fp; - char genbuf[STRLEN]; - - STATINC(STAT_FRIENDDESC); - if((set_friend_bit(currutmp,uentp)&IFH)==0) - return space_buf; - - setuserfile(fpath, friend_file[0]); - - STATINC(STAT_FRIENDDESC_FILE); - if ((fp = fopen(fpath, "r"))) { - snprintf(name, sizeof(name), "%s ", uentp->userid); - len = strlen(name); - desc = genbuf + 13; - - /* TODO maybe none linear search, or fread, or cache */ - while ((flag = fgets(genbuf, STRLEN, fp))) { - if (!memcmp(genbuf, name, len)) { - if ((ptr = strchr(desc, '\n'))) - ptr[0] = '\0'; - break; - } - } - fclose(fp); - if (flag) - strlcpy(desc_buf, desc, desc_buflen); - else - return space_buf; - - return desc_buf; - } else - return space_buf; -} - -static const char * -descript(int show_mode, const userinfo_t * uentp, int diff) -{ - static char description[30]; - switch (show_mode) { - case 1: - return friend_descript(uentp, description, sizeof(description)); - case 0: - return (((uentp->pager != PAGER_DISABLE && uentp->pager != PAGER_ANTIWB && diff) || - HasUserPerm(PERM_SYSOP)) ? -#ifdef WHERE - uentp->from_alias ? SHM->home_desc[uentp->from_alias] : - uentp->from -#else - uentp->from -#endif - : "*"); - case 2: - snprintf(description, sizeof(description), - "%4d/%4d/%2d %c", uentp->five_win, - uentp->five_lose, uentp->five_tie, - (uentp->withme&WITHME_FIVE)?'o':(uentp->withme&WITHME_NOFIVE)?'x':' '); - return description; - case 3: - snprintf(description, sizeof(description), - "%4d/%4d/%2d %c", uentp->chc_win, - uentp->chc_lose, uentp->chc_tie, - (uentp->withme&WITHME_CHESS)?'o':(uentp->withme&WITHME_NOCHESS)?'x':' '); - return description; - case 4: - snprintf(description, sizeof(description), - "%4d %s", uentp->chess_elo_rating, - (uentp->withme&WITHME_CHESS)?"§ä§Ú¤U´Ñ":(uentp->withme&WITHME_NOCHESS)?"§O§ä§Ú":""); - return description; - case 5: - snprintf(description, sizeof(description), - "%4d/%4d/%2d %c", uentp->go_win, - uentp->go_lose, uentp->go_tie, - (uentp->withme&WITHME_GO)?'o':(uentp->withme&WITHME_NOGO)?'x':' '); - return description; - default: - syslog(LOG_WARNING, "damn!!! what's wrong?? show_mode = %d", - show_mode); - return ""; - } -} - -/* - * userlist - * - * ¦³§O©ó¨ä¥L¤j³¡¥÷ bbs¦b¹ê§@¨Ï¥ÎªÌ¦W³æ®É, ³£¬O±N©Ò¦³ online users ¨ú¤@¥÷¨ì - * local space ¤¤, «ö·Ó©Ò¶·nªº¤è¦¡ sort ¦n (¦p«ö·Ó userid , ¤¤l´Ñ, ¨Ó·½µ¥ - * µ¥) . ³o±N³y¦¨¤j¶qªº®ö¶O: ¬°¤°»ò¨CÓ¤H³£n¬°¤F²£¥Í³o¤@¶¶È 20 Ó¤Hªº¸ê®Æ - * ¦Ó¥h sort ¨ä¥L¤@¸U¤Hªº¸ê®Æ? - * - * ¤@¯ë¨Ó»¡, ¤@¥÷§¹¾ãªº¨Ï¥ÎªÌ¦W³æ¥i¥H¤À¦¨¡u¦n¤Í°Ï¡v©M¡u«D¦n¤Í°Ï¡v. ¤£¦P¤Hªº - * ¡u¦n¤Í°Ï¡vÀ³¸Ó·|ªøªº¤£¤@¼Ë, ¤£¹L¡u«D¦n¤Í°Ï¡vÀ³¸Ó¬Oªøªº¤@¼Ëªº. °w¹ï³o¶µ¯S - * ©Ê, ¨â°Ï¦³¤£¦Pªº¹ê§@¤è¦¡. - * - * + ¦n¤Í°Ï - * ¦n¤Í°Ï¥u¦³¦b±Æ¦C¤è¦¡¬° [¶Ù! ªB¤Í] ªº®ÉÔ¡u¥i¯à¡v·|¥Î¨ì. - * ¨CÓ process¥i¥H³z¹L currutmp->friend_online[]±o¨ì¤¬¬Û¶¡¦³¦n¤ÍÃö«Yªº¸ê - * ®Æ (¤£¥]¬AªO¤Í, ªO¤Í¬O¥t¥~¥Í¥X¨Óªº) ¤£¹L friend_online[]¬O unorderªº. - * ©Ò¥H¶·n¥ý§â©Ò¦³ªº¤H®³¥X¨Ó, «·s sort ¤@¦¸. - * ¦n¤Í°Ï (¤¬¬Û¥ô¤@¤è¦³³]¦n¤Í+ ªO¤Í) ³Ì¦h¥u·|¦³ MAX_FRIENDSÓ - * ¦]¬°²£¥Í¦n¤Í°Ïªº cost ¬Û·í°ª, "¯à¤£²£¥Í´N¤£n²£¥Í" - * - * + «D¦n¤Í°Ï - * ³z¹L shmctl utmpsortd , ©w´Á (³q±`¤@¬í¤@¦¸) ±N¥þ¯¸ªº¤H«ö·Ó¦UºØ¤£¦Pªº¤è - * ¦¡ sort ¦n, ©ñ¸m¦b SHM->sorted¤¤. - * - * ±µ¤U¨Ó, §Ų́C¦¸¥u±q½T©wªº°_©l¦ì¸m®³, ¯S§O¬O°£«D¦³¶·n, ¤£µM¤£·|¥h²£¥Í¦n - * ¤Í°Ï. - * - * ¦UÓ function ºKn - * sort_cmpfriend() sort function, key: friend type - * pickup_maxpages() # pages of userlist - * pickup_myfriend() ²£¥Í¦n¤Í°Ï - * pickup_bfriend() ²£¥ÍªO¤Í - * pickup() ²£¥Í¬Y¤@¶¨Ï¥ÎªÌ¦W³æ - * draw_pickup() §âµe±¿é¥X - * userlist() ¥D¨ç¦¡, t³d©I¥s pickup()/draw_pickup() ¥H¤Î«öÁä³B²z - * - * SEE ALSO - * include/pttstruct.h - * - * BUGS - * ·j´Mªº®ÉÔ¨S¦³¿ìªk²¾¨ì¸Ó¤H¤W± - * - * AUTHOR - * in2 <in2@in2home.org> - */ -char nPickups; - -static int -sort_cmpfriend(const void *a, const void *b) -{ - if (((((pickup_t *) a)->friend) & ST_FRIEND) == - ((((pickup_t *) b)->friend) & ST_FRIEND)) - return strcasecmp(((pickup_t *) a)->ui->userid, - ((pickup_t *) b)->ui->userid); - else - return (((pickup_t *) b)->friend & ST_FRIEND) - - (((pickup_t *) a)->friend & ST_FRIEND); -} - -int -pickup_maxpages(int pickupway, int nfriends) -{ - int number; - if (cuser.uflag & FRIEND_FLAG) - number = nfriends; - else - number = SHM->UTMPnumber + - (pickupway == 0 ? nfriends : 0); - return (number - 1) / nPickups + 1; -} - -static int -pickup_myfriend(pickup_t * friends, - int *myfriend, int *friendme, int *badfriend) -{ - userinfo_t *uentp; - int i, where, frstate, ngets = 0; - - STATINC(STAT_PICKMYFRIEND); - *badfriend = 0; - *myfriend = *friendme = 1; - for (i = 0; currutmp->friend_online[i] && i < MAX_FRIEND; ++i) { - where = currutmp->friend_online[i] & 0xFFFFFF; - if (VALID_USHM_ENTRY(where) && - (uentp = &SHM->uinfo[where]) && uentp->pid && - uentp != currutmp && - isvisible_stat(currutmp, uentp, - frstate = - currutmp->friend_online[i] >> 24)){ - if( frstate & IRH ) - ++*badfriend; - if( !(frstate & IRH) || ((frstate & IRH) && (frstate & IFH)) ){ - friends[ngets].ui = uentp; - friends[ngets].uoffset = where; - friends[ngets++].friend = frstate; - if (frstate & IFH) - ++* myfriend; - if (frstate & HFM) - ++* friendme; - } - } - } - /* §â¦Û¤v¥[¤J¦n¤Í°Ï */ - friends[ngets].ui = currutmp; - friends[ngets++].friend = (IFH | HFM); - return ngets; -} - -static int -pickup_bfriend(pickup_t * friends, int base) -{ - userinfo_t *uentp; - int i, ngets = 0; - int currsorted = SHM->currsorted, number = SHM->UTMPnumber; - - STATINC(STAT_PICKBFRIEND); - friends = friends + base; - for (i = 0; i < number && ngets < MAX_FRIEND - base; ++i) { - uentp = &SHM->uinfo[SHM->sorted[currsorted][0][i]]; - /* TODO isvisible() «½Æ¥Î¨ì¤F friend_stat() */ - if (uentp && uentp->pid && uentp->brc_id == currutmp->brc_id && - currutmp != uentp && isvisible(currutmp, uentp) && - (base || !(friend_stat(currutmp, uentp) & (IFH | HFM)))) { - friends[ngets].ui = uentp; - friends[ngets++].friend = IBH; - } - } - return ngets; -} - -static void -pickup(pickup_t * currpickup, int pickup_way, int *page, - int *nfriend, int *myfriend, int *friendme, int *bfriend, int *badfriend) -{ - /* avoid race condition */ - int currsorted = SHM->currsorted; - int utmpnumber = SHM->UTMPnumber; - int friendtotal = currutmp->friendtotal; - - int *ulist; - userinfo_t *u; - int which, sorted_way, size = 0, friend; - - if (friendtotal == 0) - *myfriend = *friendme = 1; - - /* ²£¥Í¦n¤Í°Ï */ - which = *page * nPickups; - if( (cuser.uflag & FRIEND_FLAG) || /* ¥uÅã¥Ü¦n¤Í¼Ò¦¡ */ - ((pickup_way == 0) && /* [¶Ù! ªB¤Í] mode */ - ( - /* §tªO¤Í, ¦n¤Í°Ï³Ì¦h¥u·|¦³ (friendtotal + ªO¤Í) Ó*/ - (currutmp->brc_id && which < (friendtotal + 1 + - getbcache(currutmp->brc_id)->nuser)) || - - /* ¤£§tªO¤Í, ³Ì¦h¥u·|¦³ friendtotalÓ */ - (!currutmp->brc_id && which < friendtotal + 1) - ))) { - pickup_t friends[MAX_FRIEND]; - - /* TODO ·í friendtotal<which ®É¥u»ÝÅã¥ÜªO¤Í, ¤£»Ý pickup_myfriend */ - *nfriend = pickup_myfriend(friends, myfriend, friendme, badfriend); - - if (pickup_way == 0 && currutmp->brc_id != 0 -#ifdef USE_COOLDOWN - && !(getbcache(currutmp->brc_id)->brdattr & BRD_COOLDOWN) -#endif - ){ - /* TODO ¥u»Ýn which+nPickups-*nfriend ÓªO¤Í, ¤£¤@©wn¾ãÓ±½¤@¹M */ - *nfriend += pickup_bfriend(friends, *nfriend); - *bfriend = SHM->bcache[currutmp->brc_id - 1].nuser; - } - else - *bfriend = 0; - if (*nfriend > which) { - /* ¥u¦³¦bn¨q¥X¤~¦³¥²n sort */ - /* TODO ¦n¤Í¸òªO¤Í¥i¥H¤À¶} sort, ¥i¯à¥u»Ýn¨ä¤@ */ - /* TODO ¦n¤Í¤W¤U¯¸¤~»Ýn sort ¤@¦¸, ¤£»Ýn¨C¦¸ sort. - * ¥iºûÅ@¤@Ó dirty bit ªí¥Ü¬O§_ sort ¹L. - * suggested by WYchuang@ptt */ - qsort(friends, *nfriend, sizeof(pickup_t), sort_cmpfriend); - size = *nfriend - which; - if (size > nPickups) - size = nPickups; - memcpy(currpickup, friends + which, sizeof(pickup_t) * size); - } - } else - *nfriend = 0; - - if (!(cuser.uflag & FRIEND_FLAG) && size < nPickups) { - sorted_way = ((pickup_way == 0) ? 7 : (pickup_way - 1)); - ulist = SHM->sorted[currsorted][sorted_way]; - which = *page * nPickups - *nfriend; - if (which < 0) - which = 0; - - for (; which < utmpnumber && size < nPickups; which++) { - u = &SHM->uinfo[ulist[which]]; - - friend = friend_stat(currutmp, u); - /* TODO isvisible() «½Æ¥Î¨ì¤F friend_stat() */ - if ((pickup_way || - (currutmp != u && !(friend & ST_FRIEND))) && - isvisible(currutmp, u)) { - currpickup[size].ui = u; - currpickup[size++].friend = friend; - } - } - } - - for (; size < nPickups; ++size) - currpickup[size].ui = 0; -} - -static void -draw_pickup(int drawall, pickup_t * pickup, int pickup_way, - int page, int show_mode, int show_uid, int show_board, - int show_pid, int myfriend, int friendme, int bfriend, int badfriend) -{ - char *msg_pickup_way[PICKUP_WAYS] = { - "¶Ù! ªB¤Í", "ºô¤Í¥N¸¹", "ºô¤Í°ÊºA", "µo§b®É¶¡", "¨Ó¦Û¦ó¤è", " ¤¤l´Ñ ", " ¶H´Ñ ", " ³ò´Ñ ", - }; - char *MODE_STRING[MAX_SHOW_MODE] = { - "¬G¶m", "¦n¤Í´yz", "¤¤l´Ñ¾ÔÁZ", "¶H´Ñ¾ÔÁZ", "¶H´Ñµ¥¯Å¤À", "³ò´Ñ¾ÔÁZ", - }; - char pagerchar[5] = "* -Wf"; - - userinfo_t *uentp; - int i, ch, state, friend; - char mind[5]; - -#ifdef SHOW_IDLE_TIME - char idlestr[32]; - int idletime; -#endif - - /* wide screen support */ - int wNick = 17, wMode = 12; //13; , one byte give number for ptt always > 10000 online. - - if (t_columns > 80) - { - int d = t_columns - 80; - - /* rule: try to give extra space to both nick and mode, - * because nick is smaller, try nick first then mode. */ - if (d >= sizeof(cuser.nickname) - wNick) - { - d -= (sizeof(cuser.nickname) - wNick); - wNick = sizeof(cuser.nickname); - wMode += d; - } else { - wNick += d; - } - } - - if (drawall) { - showtitle((cuser.uflag & FRIEND_FLAG) ? "¦n¤Í¦Cªí" : "¥ð¶¢²á¤Ñ", - BBSName); - prints("\n" - ANSI_COLOR(7) " %s P%c¥N¸¹ %-*s%-17s%-*s%10s" - ANSI_RESET "\n", - show_uid ? "UID " : "½s¸¹", - (HasUserPerm(PERM_SEECLOAK) || HasUserPerm(PERM_SYSOP)) ? - 'C' : ' ', - wNick, "¼ÊºÙ", - MODE_STRING[show_mode], - wMode, show_board ? "Board" : "°ÊºA", - show_pid ? " PID" : "¤ß±¡ " -#ifdef SHOW_IDLE_TIME - "µo§b" -#else - " " -#endif - ); - move(b_lines, 0); - outslr( - ANSI_COLOR(34;46) " ¥ð¶¢²á¤Ñ " - ANSI_COLOR(31;47) " (TAB/f)" ANSI_COLOR(30) "±Æ§Ç/¦n¤Í " - ANSI_COLOR(31) "(a/o)" ANSI_COLOR(30) "¥æ¤Í " - ANSI_COLOR(31) "(q/w)" ANSI_COLOR(30) "¬d¸ß/¥á¤ô²y " - ANSI_COLOR(31) "(t/m)" ANSI_COLOR(30) "²á¤Ñ/¼g«H ", - 80-10, - ANSI_COLOR(31) "(h)" ANSI_COLOR(30) "»¡©ú " ANSI_RESET, - 8); - } - move(1, 0); - prints(" ±Æ§Ç:[%s] ¤W¯¸¤H¼Æ:%-4d " - ANSI_COLOR(1;32) "§ÚªºªB¤Í:%-3d " - ANSI_COLOR(33) "»P§Ú¬°¤Í:%-3d " - ANSI_COLOR(36) "ªO¤Í:%-4d " - ANSI_COLOR(31) "Ãa¤H:%-2d" - ANSI_RESET "\n", - msg_pickup_way[pickup_way], SHM->UTMPnumber, - myfriend, friendme, currutmp->brc_id ? bfriend : 0, badfriend); - - for (i = 0, ch = page * nPickups + 1; i < nPickups; ++i, ++ch) { - move(i + 3, 0); - outc('a'); - move(i + 3, 0); - uentp = pickup[i].ui; - friend = pickup[i].friend; - if (uentp == NULL) { - outc('\n'); - continue; - } - if (!uentp->pid) { - prints("%5d < Â÷¯¸¤¤..>\n", ch); - continue; - } - if (PERM_HIDE(uentp)) - state = 9; - else if (currutmp == uentp) - state = 10; - else if (friend & IRH && !(friend & IFH)) - state = 8; - else - state = (friend & ST_FRIEND) >> 2; - -#ifdef SHOW_IDLE_TIME - idletime = (now - uentp->lastact); - if (idletime > 86400) - strlcpy(idlestr, " -----", sizeof(idlestr)); - else if (idletime >= 3600) - snprintf(idlestr, sizeof(idlestr), "%3dh%02d", - idletime / 3600, (idletime / 60) % 60); - else if (idletime > 0) - snprintf(idlestr, sizeof(idlestr), "%3d'%02d", - idletime / 60, idletime % 60); - else - strlcpy(idlestr, " ", sizeof(idlestr)); -#endif - - if ((uentp->userlevel & PERM_VIOLATELAW)) - memcpy(mind, "³q½r", 4); - else if (uentp->birth) - memcpy(mind, "¹Ø¬P", 4); - else - memcpy(mind, uentp->mind, 4); - mind[4] = 0; - - /* TODO - * will this be faster if we use pure outc/outs? - */ - prints("%7d %c%c%s%-13s%-*.*s " ANSI_RESET "%-16.16s %-*.*s" - ANSI_COLOR(33) "%-4.4s" ANSI_RESET "%s\n", - - /* list number or uid */ -#ifdef SHOWUID - show_uid ? uentp->uid : -#endif - ch, - - /* super friend or pager */ - (friend & HRM) ? 'X' : pagerchar[uentp->pager % 5], - - /* visibility */ - (uentp->invisible ? ')' : ' '), - - /* color of userid, userid */ - fcolor[state], uentp->userid, - - /* nickname */ - wNick-1, wNick-1, uentp->nickname, - - /* from */ - descript(show_mode, uentp, - uentp->pager & !(friend & HRM)), - - /* board or mode */ - wMode, wMode, -#if defined(SHOWBOARD) && defined(DEBUG) - show_board ? (uentp->brc_id == 0 ? "" : - getbcache(uentp->brc_id)->brdname) : -#endif - modestring(uentp, 0), - - /* memo */ - mind, - - /* idle */ -#ifdef SHOW_IDLE_TIME - idlestr -#else - "" -#endif - ); - - //refresh(); - } -} - -void set_withme_flag(void) -{ - int i; - char genbuf[20]; - int line; - - move(1, 0); - clrtobot(); - - do { - move(1, 0); - line=1; - for(i=0; i<16 && withme_str[i]; i++) { - clrtoeol(); - if(currutmp->withme&(1<<(i*2))) - prints("[%c] §Ú«Ü·Q¸ò¤H%s, Åwªï¥ô¦ó¤H§ä§Ú\n",'a'+i, withme_str[i]); - else if(currutmp->withme&(1<<(i*2+1))) - prints("[%c] §Ú¤£¤Ó·Q%s\n",'a'+i, withme_str[i]); - else - prints("[%c] (%s)¨S·N¨£\n",'a'+i, withme_str[i]); - line++; - } - getdata(line,0,"¥Î¦r¥À¤Á´« [·Q/¤£·Q/¨S·N¨£]",genbuf, sizeof(genbuf), DOECHO); - for(i=0;genbuf[i];i++) { - int ch=genbuf[i]; - ch=tolower(ch); - if('a'<=ch && ch<'a'+16) { - ch-='a'; - if(currutmp->withme&(1<<ch*2)) { - currutmp->withme&=~(1<<ch*2); - currutmp->withme|=1<<(ch*2+1); - } else if(currutmp->withme&(1<<(ch*2+1))) { - currutmp->withme&=~(1<<(ch*2+1)); - } else { - currutmp->withme|=1<<(ch*2); - } - } - } - } while(genbuf[0]!='\0'); -} - -int -call_in(const userinfo_t * uentp, int fri_stat) -{ - if (iswritable_stat(uentp, fri_stat)) { - char genbuf[60]; - snprintf(genbuf, sizeof(genbuf), "¥á %s ¤ô²y: ", uentp->userid); - my_write(uentp->pid, genbuf, uentp->userid, WATERBALL_GENERAL, NULL); - return 1; - } - return 0; -} - -inline static void -userlist(void) -{ - pickup_t *currpickup; - userinfo_t *uentp; - static char show_mode = 0; - static char show_uid = 0; - static char show_board = 0; - static char show_pid = 0; - static int pickup_way = 0; - char skippickup = 0, redraw, redrawall; - int page, offset, ch, leave, fri_stat; - int nfriend, myfriend, friendme, bfriend, badfriend, i; - time4_t lastupdate; - - nPickups = b_lines - 3; - currpickup = (pickup_t *)malloc(sizeof(pickup_t) * nPickups); - page = offset = 0 ; - nfriend = myfriend = friendme = bfriend = badfriend = 0; - leave = 0; - redrawall = 1; - /* - * ¦UÓ flag : - * redraw: «·s pickup(), draw_pickup() (¶È¤¤¶¡°Ï, ¤£§t¼ÐÃD¦Cµ¥µ¥) - * redrawall: ¥þ³¡«µe (§t¼ÐÃD¦Cµ¥µ¥, ¶·¦A«ü©w redraw ¤~·|¦³®Ä) - * leave: Â÷¶}¨Ï¥ÎªÌ¦W³æ - */ - while (!leave) { - if( !skippickup ) - pickup(currpickup, pickup_way, &page, - &nfriend, &myfriend, &friendme, &bfriend, &badfriend); - draw_pickup(redrawall, currpickup, pickup_way, page, - show_mode, show_uid, show_board, show_pid, - myfriend, friendme, bfriend, badfriend); - - /* - * ¦pªG¦]¬°´«¶ªº®ÉÔ, ³o¤@¶¦³ªº¤H¼Æ¤ñ¸û¤Ö, - * (³q±`³£¬O³Ì«á¤@¶¤H¼Æ¤£º¡ªº®ÉÔ) ¨ºn«·spºâ offset - * ¥H§K«ü¨ì¨S¦³¤Hªº¦a¤è - */ - if (offset == -1 || currpickup[offset].ui == NULL) { - for (offset = (offset == -1 ? nPickups - 1 : offset); - offset >= 0; --offset) - if (currpickup[offset].ui != NULL) - break; - if (offset == -1) { - if (--page < 0) - page = pickup_maxpages(pickup_way, nfriend) - 1; - offset = 0; - continue; - } - } - skippickup = redraw = redrawall = 0; - lastupdate = now; - while (!redraw) { - ch = cursor_key(offset + 3, 0); - uentp = currpickup[offset].ui; - fri_stat = currpickup[offset].friend; - - switch (ch) { - case KEY_LEFT: - case 'e': - case 'E': - redraw = leave = 1; - break; - - case KEY_TAB: - pickup_way = (pickup_way + 1) % PICKUP_WAYS; - redraw = 1; - redrawall = 1; - break; - - case KEY_DOWN: - case 'n': - case 'j': - if (++offset == nPickups || currpickup[offset].ui == NULL) { - redraw = 1; - if (++page >= pickup_maxpages(pickup_way, - nfriend)) - offset = page = 0; - else - offset = 0; - } - break; - - case '0': - case KEY_HOME: - page = offset = 0; - redraw = 1; - break; - - case 'H': - if (HasUserPerm(PERM_SYSOP)||HasUserPerm(PERM_OLDSYSOP)) { - currutmp->userlevel ^= PERM_SYSOPHIDE; - redrawall = redraw = 1; - } - break; - - case 'C': -#if !HAVE_FREECLOAK - if (HasUserPerm(PERM_CLOAK)) -#endif - { - currutmp->invisible ^= 1; - redrawall = redraw = 1; - } - break; - - case ' ': - case KEY_PGDN: - case Ctrl('F'):{ - int newpage; - if ((newpage = page + 1) >= pickup_maxpages(pickup_way, - nfriend)) - newpage = offset = 0; - if (newpage != page) { - page = newpage; - redraw = 1; - } else if (now >= lastupdate + 2) - redrawall = redraw = 1; - } - break; - - case KEY_UP: - case 'k': - if (--offset == -1) { - offset = nPickups - 1; - if (--page == -1) - page = pickup_maxpages(pickup_way, nfriend) - - 1; - redraw = 1; - } - break; - - case KEY_PGUP: - case Ctrl('B'): - case 'P': - if (--page == -1) - page = pickup_maxpages(pickup_way, nfriend) - 1; - offset = 0; - redraw = 1; - break; - - case KEY_END: - case '$': - page = pickup_maxpages(pickup_way, nfriend) - 1; - offset = -1; - redraw = 1; - break; - - case '/': - /* - * getdata_buf(b_lines-1,0,"½Ð¿é¤J¼ÊºÙÃöÁä¦r:", keyword, - * sizeof(keyword), DOECHO); state = US_PICKUP; - */ - break; - - case 's': - if (!(cuser.uflag & FRIEND_FLAG)) { - int si; /* utmpshm->sorted[X][0][si] */ - int fi; /* allpickuplist[fi] */ - char swid[IDLEN + 1]; - move(1, 0); - si = CompleteOnlineUser(msg_uid, swid); - if (si >= 0) { - pickup_t friends[MAX_FRIEND + 1]; - int nGots, i; - int *ulist = - SHM->sorted[SHM->currsorted] - [((pickup_way == 0) ? 0 : (pickup_way - 1))]; - - fi = ulist[si]; - nGots = pickup_myfriend(friends, &myfriend, - &friendme, &badfriend); - for (i = 0; i < nGots; ++i) - if (friends[i].uoffset == fi) - break; - - fi = 0; - offset = 0; - if( i != nGots ){ - page = i / nPickups; - for( ; i < nGots && fi < nPickups ; ++i ) - if( isvisible(currutmp, friends[i].ui) ) - currpickup[fi++] = friends[i]; - i = 0; - } - else{ - page = (si + nGots) / nPickups; - i = si; - } - - for( ; fi < nPickups && i < SHM->UTMPnumber ; ++i ) - { - userinfo_t *u; - u = &SHM->uinfo[ulist[i]]; - if( isvisible(currutmp, u) ){ - currpickup[fi].ui = u; - currpickup[fi++].friend = 0; - } - } - skippickup = 1; - } - redrawall = redraw = 1; - } - /* - * if ((i = search_pickup(num, actor, pklist)) >= 0) num = i; - * state = US_ACTION; - */ - break; - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { /* Thor: ¥i¥H¥´¼Æ¦r¸õ¨ì¸Ó¤H */ - int tmp; - if ((tmp = search_num(ch, SHM->UTMPnumber)) >= 0) { - if (tmp / nPickups == page) { - /* - * in2:¥Øªº¦b¥Ø«e³o¤@¶, ª½±µ §ó·s offset , - * ¤£¥Î«µeµe± - */ - offset = tmp % nPickups; - } else { - page = tmp / nPickups; - offset = tmp % nPickups; - } - redrawall = redraw = 1; - } - } - break; - -#ifdef SHOWUID - case 'U': - if (HasUserPerm(PERM_SYSOP)) { - show_uid ^= 1; - redrawall = redraw = 1; - } - break; -#endif -#if defined(SHOWBOARD) && defined(DEBUG) - case 'Y': - if (HasUserPerm(PERM_SYSOP)) { - show_board ^= 1; - redrawall = redraw = 1; - } - break; -#endif -#ifdef SHOWPID - case '#': - if (HasUserPerm(PERM_SYSOP)) { - show_pid ^= 1; - redrawall = redraw = 1; - } - break; -#endif - - case 'b': /* broadcast */ - if (cuser.uflag & FRIEND_FLAG || HasUserPerm(PERM_SYSOP)) { - char genbuf[60]="[¼s¼½]"; - char ans[4]; - - if (!getdata(0, 0, "¼s¼½°T®§:", genbuf+6, 54, DOECHO)) - break; - - if (!getdata(0, 0, "½T©w¼s¼½? [N]", - ans, sizeof(ans), LCECHO) || - ans[0] != 'y') - break; - if (!(cuser.uflag & FRIEND_FLAG) && HasUserPerm(PERM_SYSOP)) { - msgque_t msg; - getdata(1, 0, "¦A¦¸½T©w¯¸ªø¼s¼½? [N]", - ans, sizeof(ans), LCECHO); - if( ans[0] != 'y' && ans[0] != 'Y' ){ - vmsg("abort"); - break; - } - - msg.pid = currpid; - strlcpy(msg.userid, cuser.userid, sizeof(msg.userid)); - snprintf(msg.last_call_in, sizeof(msg.last_call_in), - "[¼s¼½]%s", genbuf); - for (i = 0; i < SHM->UTMPnumber; ++i) { - // XXX why use sorted list? - // can we just scan uinfo with proper checking? - uentp = &SHM->uinfo[ - SHM->sorted[SHM->currsorted][0][i]]; - if (uentp->pid && kill(uentp->pid, 0) != -1){ - int write_pos = uentp->msgcount; - if( write_pos < (MAX_MSGS - 1) ){ - uentp->msgcount = write_pos + 1; - memcpy(&uentp->msgs[write_pos], &msg, - sizeof(msg)); -#ifdef NOKILLWATERBALL - uentp->wbtime = now; -#else - kill(uentp->pid, SIGUSR2); -#endif - } - } - } - } else { - userinfo_t *uentp; - int where, frstate; - for (i = 0; currutmp->friend_online[i] && - i < MAX_FRIEND; ++i) { - where = currutmp->friend_online[i] & 0xFFFFFF; - if (VALID_USHM_ENTRY(where) && - (uentp = &SHM->uinfo[where]) && - uentp->pid && - isvisible_stat(currutmp, uentp, - frstate = - currutmp->friend_online[i] >> 24) - && kill(uentp->pid, 0) != -1 && - uentp->pager != PAGER_ANTIWB && - (uentp->pager != PAGER_FRIENDONLY || frstate & HFM) && - !(frstate & IRH)) { - my_write(uentp->pid, genbuf, uentp->userid, - WATERBALL_PREEDIT, NULL); - } - } - } - redrawall = redraw = 1; - } - break; - - case 'S': /* Åã¥Ü¦n¤Í´yz */ - show_mode = (show_mode+1) % MAX_SHOW_MODE; -#ifdef CHESSCOUNTRY - if (show_mode == 2) - user_query_mode = 1; - else if (show_mode == 3 || show_mode == 4) - user_query_mode = 2; - else if (show_mode == 5) - user_query_mode = 3; - else - user_query_mode = 0; -#endif /* defined(CHESSCOUNTRY) */ - redrawall = redraw = 1; - break; - - case 'u': /* ½u¤Wקï¸ê®Æ */ - if (HasUserPerm(PERM_ACCOUNTS|PERM_SYSOP)) { - int id; - userec_t muser; - strlcpy(currauthor, uentp->userid, sizeof(currauthor)); - stand_title("¨Ï¥ÎªÌ³]©w"); - move(1, 0); - if ((id = getuser(uentp->userid, &muser)) > 0) { - user_display(&muser, 1); - if( HasUserPerm(PERM_ACCOUNTS) ) - uinfo_query(&muser, 1, id); - else - pressanykey(); - } - redrawall = redraw = 1; - } - break; - - case 'i':{ - char mindbuf[5]; - getdata(b_lines - 1, 0, "²{¦bªº¤ß±¡? ", - mindbuf, sizeof(mindbuf), DOECHO); - if (strcmp(mindbuf, "³q½r") == 0) - vmsg("¤£¥i¥H§â¦Û¤v³]³q½r°Õ!"); - else if (strcmp(mindbuf, "¹Ø¬P") == 0) - vmsg("§A¤£¬O¤µ¤Ñ¥Í¤éÕÙ!"); - else - memcpy(currutmp->mind, mindbuf, 4); - } - redrawall = redraw = 1; - break; - - case Ctrl('S'): - break; - - case KEY_RIGHT: - case '\n': - case '\r': - case 't': - if (HasUserPerm(PERM_LOGINOK)) { - if (uentp->pid != currpid && - strcmp(uentp->userid, cuser.userid) != 0) { - move(1, 0); - clrtobot(); - move(3, 0); - my_talk(uentp, fri_stat, 0); - redrawall = redraw = 1; - } - } - break; - case 'K': - if (HasUserPerm(PERM_ACCOUNTS|PERM_SYSOP)) { - my_kick(uentp); - redrawall = redraw = 1; - } - break; - case 'w': - if (call_in(uentp, fri_stat)) - redrawall = redraw = 1; - break; - case 'a': - if (HasUserPerm(PERM_LOGINOK) && !(fri_stat & IFH)) { - if (getans("½T©wn¥[¤J¦n¤Í¶Ü [N/y]") == 'y') { - friend_add(uentp->userid, FRIEND_OVERRIDE,uentp->nickname); - friend_load(FRIEND_OVERRIDE); - } - redrawall = redraw = 1; - } - break; - - case 'd': - if (HasUserPerm(PERM_LOGINOK) && (fri_stat & IFH)) { - if (getans("½T©wn§R°£¦n¤Í¶Ü [N/y]") == 'y') { - friend_delete(uentp->userid, FRIEND_OVERRIDE); - friend_load(FRIEND_OVERRIDE); - } - redrawall = redraw = 1; - } - break; - - case 'o': - if (HasUserPerm(PERM_LOGINOK)) { - t_override(); - redrawall = redraw = 1; - } - break; - - case 'f': - if (HasUserPerm(PERM_LOGINOK)) { - cuser.uflag ^= FRIEND_FLAG; - redrawall = redraw = 1; - } - break; - - case 'g': - if (HasUserPerm(PERM_LOGINOK) && - strcmp(uentp->userid, cuser.userid) != 0) { - give_money_ui(uentp->userid); - redrawall = redraw = 1; - } - break; - - case 'm': - if (HasUserPerm(PERM_LOGINOK)) { - char userid[IDLEN + 1]; - strlcpy(userid, uentp->userid, sizeof(userid)); - stand_title("±H «H"); - prints("[±H«H] ¦¬«H¤H¡G%s", userid); - my_send(userid); - setutmpmode(LUSERS); - redrawall = redraw = 1; - } - break; - - case 'q': - strlcpy(currauthor, uentp->userid, sizeof(currauthor)); - my_query(uentp->userid); - setutmpmode(LUSERS); - redrawall = redraw = 1; - break; - - case 'c': - if (HasUserPerm(PERM_LOGINOK)) { - chicken_query(uentp->userid); - redrawall = redraw = 1; - } - break; - - case 'l': - if (HasUserPerm(PERM_LOGINOK)) { - t_display(); - redrawall = redraw = 1; - } - break; - - case 'h': - t_showhelp(); - redrawall = redraw = 1; - break; - - case 'p': - if (HasUserPerm(PERM_BASIC)) { - t_pager(); - redrawall = redraw = 1; - } - break; - - case Ctrl('W'): - if (HasUserPerm(PERM_LOGINOK)) { - int tmp; - char *wm[3] = {"¤@¯ë", "¶i¶¥", "¥¼¨Ó"}; - tmp = cuser.uflag2 & WATER_MASK; - cuser.uflag2 -= tmp; - tmp = (tmp + 1) % 3; - cuser.uflag2 |= tmp; - /* vmsg cannot support multi lines */ - move(b_lines - 4, 0); - clrtobot(); - move(b_lines - 3, 0); - outs("¨t²Î´£¨Ñ ¤@¯ë ¶i¶¥ ¥¼¨Ó ¤TºØ¼Ò¦¡\n" - "¦b¤Á´««á½Ð¥¿±`¤U½u¦A«·sµn¤J, ¥H½T«Oµ²ºc¥¿½T\n"); - vmsgf( "¥Ø«e¤Á´«¨ì %s ¤ô²y¼Ò¦¡", wm[tmp]); - redrawall = redraw = 1; - } - break; - - case 'r': - if (HasUserPerm(PERM_LOGINOK)) { - if (curredit & EDIT_MAIL) { - /* deny reentrance, which may cause many problems */ - vmsg("§A¶i¤J¨Ï¥ÎªÌ¦Cªí«e´N¤w¸g¦b¾\\Ū«H¥ó¤F"); - } else { - // XXX in fact we should check size here... - // chkmailbox(); - m_read(); - setutmpmode(LUSERS); - } - redrawall = redraw = 1; - } - break; - - case 'N': - if (HasUserPerm(PERM_LOGINOK)) { - char tmp_nick[sizeof(cuser.nickname)]; - // XXX why do so many copy here? - // why not just use cuser.nickname? - // XXX old code forget to initialize. - // will changing to init everytime cause user - // complain? - - strlcpy(tmp_nick, currutmp->nickname, sizeof(cuser.nickname)); - - if (oldgetdata(1, 0, "·sªº¼ÊºÙ: ", - tmp_nick, sizeof(tmp_nick), DOECHO) > 0) - { - strlcpy(cuser.nickname, tmp_nick, sizeof(cuser.nickname)); - strcpy(currutmp->nickname, cuser.nickname); - } - redrawall = redraw = 1; - } - break; - - case 'y': - set_withme_flag(); - redrawall = redraw = 1; - break; - - default: - if (now >= lastupdate + 2) - redraw = 1; - } - } - } - free(currpickup); -} - -int -t_users(void) -{ - int destuid0 = currutmp->destuid; - int mode0 = currutmp->mode; - int stat0 = currstat; - - assert(strncmp(cuser.userid, currutmp->userid, IDLEN)==0); - if( strncmp(cuser.userid , currutmp->userid, IDLEN) != 0 ){ - abort_bbs(0); - } - - setutmpmode(LUSERS); - userlist(); - currutmp->mode = mode0; - currutmp->destuid = destuid0; - currstat = stat0; - return 0; -} - -int -t_pager(void) -{ - currutmp->pager = (currutmp->pager + 1) % PAGER_MODES; - return 0; -} - -int -t_idle(void) -{ - int destuid0 = currutmp->destuid; - int mode0 = currutmp->mode; - int stat0 = currstat; - char genbuf[20]; - char passbuf[PASSLEN]; - int idle_type; - char idle_reason[sizeof(currutmp->chatid)]; - - - setutmpmode(IDLE); - getdata(b_lines - 1, 0, "²z¥Ñ¡G[0]µo§b (1)±µ¹q¸Ü (2)³V¹ (3)¥´½OºÎ " - "(4)¸Ë¦º (5)ù¤¦ (6)¨ä¥L (Q)¨S¨Æ¡H", genbuf, 3, DOECHO); - if (genbuf[0] == 'q' || genbuf[0] == 'Q') { - currutmp->mode = mode0; - currstat = stat0; - return 0; - } else if (genbuf[0] >= '1' && genbuf[0] <= '6') - idle_type = genbuf[0] - '0'; - else - idle_type = 0; - - if (idle_type == 6) { - if (cuser.userlevel && getdata(b_lines - 1, 0, "µo§bªº²z¥Ñ¡G", idle_reason, sizeof(idle_reason), DOECHO)) { - strlcpy(currutmp->chatid, idle_reason, sizeof(currutmp->chatid)); - } else { - idle_type = 0; - } - } - currutmp->destuid = idle_type; - do { - move(b_lines - 2, 0); - clrtobot(); - prints("(Âê©w¿Ã¹õ)µo§bì¦]: %s", (idle_type != 6) ? - IdleTypeTable[idle_type] : idle_reason); - refresh(); - getdata(b_lines - 1, 0, MSG_PASSWD, passbuf, sizeof(passbuf), NOECHO); - passbuf[8] = '\0'; - } - while (!checkpasswd(cuser.passwd, passbuf) && - strcmp(STR_GUEST, cuser.userid)); - - currutmp->mode = mode0; - currutmp->destuid = destuid0; - currstat = stat0; - - return 0; -} - -int -t_qchicken(void) -{ - char uident[STRLEN]; - - stand_title("¬d¸ßÃdª«"); - usercomplete(msg_uid, uident); - if (uident[0]) - chicken_query(uident); - return 0; -} - -int -t_query(void) -{ - char uident[STRLEN]; - - stand_title("¬d¸ßºô¤Í"); - usercomplete(msg_uid, uident); - if (uident[0]) - my_query(uident); - return 0; -} - -int -t_talk(void) -{ - char uident[16]; - int tuid, unum, ucount; - userinfo_t *uentp; - char genbuf[4]; - /* - * if (count_ulist() <= 1){ outs("¥Ø«e½u¤W¥u¦³±z¤@¤H¡A§ÖÁܽЪB¤Í¨Ó¥úÁ{¡i" - * BBSNAME "¡j§a¡I"); return XEASY; } - */ - stand_title("¥´¶}¸Ü§X¤l"); - CompleteOnlineUser(msg_uid, uident); - if (uident[0] == '\0') - return 0; - - move(3, 0); - if (!(tuid = searchuser(uident, uident)) || tuid == usernum) { - outs(err_uid); - pressanykey(); - return 0; - } - /* multi-login check */ - unum = 1; - while ((ucount = count_logins(tuid, 0)) > 1) { - outs("(0) ¤£·Q talk ¤F...\n"); - count_logins(tuid, 1); - getdata(1, 33, "½Ð¿ï¾Ü¤@Ó²á¤Ñ¹ï¶H [0]¡G", genbuf, 4, DOECHO); - unum = atoi(genbuf); - if (unum == 0) - return 0; - move(3, 0); - clrtobot(); - if (unum > 0 && unum <= ucount) - break; - } - - if ((uentp = (userinfo_t *) search_ulistn(tuid, unum))) - my_talk(uentp, friend_stat(currutmp, uentp), 0); - - return 0; -} - -int -reply_connection_request(const userinfo_t *uip) -{ - char buf[4], genbuf[200]; - - if (uip->mode != PAGE) { - snprintf(genbuf, sizeof(genbuf), - "%s¤w°±¤î©I¥s¡A«öEnterÄ~Äò...", page_requestor); - getdata(0, 0, genbuf, buf, sizeof(buf), LCECHO); - return -1; - } - return establish_talk_connection(uip); -} - -int -establish_talk_connection(const userinfo_t *uip) -{ - int a; - struct sockaddr_in sin; - - currutmp->msgcount = 0; - strlcpy(save_page_requestor, page_requestor, sizeof(save_page_requestor)); - memset(page_requestor, 0, sizeof(page_requestor)); - memset(&sin, 0, sizeof(sin)); - sin.sin_family = PF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = uip->sockaddr; - if ((a = socket(sin.sin_family, SOCK_STREAM, 0)) < 0) { - perror("socket err"); - return -1; - } - if ((connect(a, (struct sockaddr *) & sin, sizeof(sin)))) { - //perror("connect err"); - return -1; - } - return a; -} - -/* ¦³¤H¨Ó¦êªù¤l¤F¡A¦^À³©I¥s¾¹ */ -void -talkreply(void) -{ - char buf[4]; - char genbuf[200]; - int a, sig = currutmp->sig; - int currstat0 = currstat; - int r; - int is_chess; - userec_t xuser; - void (*sig_pipe_handle)(int); - - uip = &SHM->uinfo[currutmp->destuip]; - currutmp->destuid = uip->uid; - currstat = REPLY; /* ÁקK¥X²{°Êµe */ - - is_chess = (sig == SIG_CHC || sig == SIG_GOMO || sig == SIG_GO || sig == SIG_REVERSI); - - a = reply_connection_request(uip); - if (a < 0) { - clear(); - currstat = currstat0; - return; - } - if (is_chess) - ChessAcceptingRequest(a); - - clear(); - - outs("\n\n"); - // FIXME CRASH here - assert(sig>=0 && sig<sizeof(sig_des)/sizeof(sig_des[0])); - prints(" (Y) Åý§ÚÌ %s §a¡I" - " (A) §Ú²{¦b«Ü¦£¡A½Ðµ¥¤@·|¨à¦A call §Ú\n", sig_des[sig]); - prints(" (N) §Ú²{¦b¤£·Q %s" - " (B) ¹ï¤£°_¡A§Ú¦³¨Æ±¡¤£¯à¸ò§A %s\n", - sig_des[sig], sig_des[sig]); - prints(" (C) ½Ð¤£n§n§Ú¦n¶Ü¡H" - " (D) §ÚnÂ÷¯¸Åo..¤U¦¸¦A²á§a.......\n"); - prints(" (E) ¦³¨Æ¶Ü¡H½Ð¥ý¨Ó«H" - " (F) " ANSI_COLOR(1;33) "§Ú¦Û¤v¿é¤J²z¥Ñ¦n¤F..." ANSI_RESET "\n"); - prints(" (1) %s¡H¥ý®³100»È¨â¨Ó" - " (2) %s¡H¥ý®³1000»È¨â¨Ó..\n\n", sig_des[sig], sig_des[sig]); - - snprintf(page_requestor, sizeof(page_requestor), - "%s (%s)", uip->userid, uip->nickname); - getuser(uip->userid, &xuser); - currutmp->msgs[0].pid = uip->pid; - strlcpy(currutmp->msgs[0].userid, uip->userid, sizeof(currutmp->msgs[0].userid)); - strlcpy(currutmp->msgs[0].last_call_in, "©I¥s¡B©I¥s¡AÅ¥¨ì½Ð¦^µª (Ctrl-R)", - sizeof(currutmp->msgs[0].last_call_in)); - currutmp->msgs[0].msgmode = MSGMODE_TALK; - prints("¹ï¤è¨Ó¦Û [%s]¡A¦@¤W¯¸ %d ¦¸¡A¤å³¹ %d ½g\n", - uip->from, xuser.numlogins, xuser.numposts); - - if (is_chess) - ChessShowRequest(); - else { - showplans(uip->userid); - show_call_in(0, 0); - } - - snprintf(genbuf, sizeof(genbuf), - "§A·Q¸ò %s %s°Ú¡H½Ð¿ï¾Ü(Y/N/A/B/C/D/E/F/1/2)[N] ", - page_requestor, sig_des[sig]); - getdata(0, 0, genbuf, buf, sizeof(buf), LCECHO); - - if (!buf[0] || !strchr("yabcdef12", buf[0])) - buf[0] = 'n'; - - sig_pipe_handle = Signal(SIGPIPE, SIG_IGN); - r = write(a, buf, 1); - if (buf[0] == 'f' || buf[0] == 'F') { - if (!getdata(b_lines, 0, "¤£¯àªºì¦]¡G", genbuf, 60, DOECHO)) - strlcpy(genbuf, "¤£§i¶D§A«¨ !! ^o^", sizeof(genbuf)); - r = write(a, genbuf, 60); - } - Signal(SIGPIPE, sig_pipe_handle); - - if (r == -1) { - snprintf(genbuf, sizeof(genbuf), - "%s¤w°±¤î©I¥s¡A«öEnterÄ~Äò...", page_requestor); - getdata(0, 0, genbuf, buf, sizeof(buf), LCECHO); - clear(); - currstat = currstat0; - return; - } - - uip->destuip = currutmp - &SHM->uinfo[0]; - if (buf[0] == 'y') - switch (sig) { - case SIG_DARK: - main_dark(a, uip); - break; -#ifdef USE_CHICKEN_PK - case SIG_PK: - chickenpk(a); - break; -#endif // USE_CHICKEN_PK - case SIG_GOMO: - gomoku(a, CHESS_MODE_VERSUS); - break; - case SIG_CHC: - chc(a, CHESS_MODE_VERSUS); - break; - case SIG_GO: - gochess(a, CHESS_MODE_VERSUS); - break; - case SIG_REVERSI: - reversi(a, CHESS_MODE_VERSUS); - break; - case SIG_TALK: - default: - do_talk(a); - } - else - close(a); - clear(); - currstat = currstat0; -} - -#ifdef PLAY_ANGEL -/* ¤p¤Ñ¨Ï¤p¥D¤H³B²z¨ç¦¡ */ -int -t_changeangel(){ - char buf[4]; - - /* cuser.myangel == "-" means banned for calling angel */ - if (cuser.myangel[0] == '-' || cuser.myangel[1] == 0) return 0; - - getdata(b_lines - 1, 0, - "§ó´«¤p¤Ñ¨Ï«á´NµLªk´«¦^¤F³á¡I ¬O§_n§ó´«¤p¤Ñ¨Ï¡H [y/N]", - buf, 3, LCECHO); - if (buf[0] == 'y' || buf[0] == 'Y') { - char buf[100]; - snprintf(buf, sizeof(buf), "%s¤p¥D¤H %s ´«±¼ %s ¤p¤Ñ¨Ï\n", - ctime4(&now), cuser.userid, cuser.myangel); - buf[24] = ' '; // replace '\n' - log_file(BBSHOME "/log/changeangel.log", LOG_CREAT, buf); - - cuser.myangel[0] = 0; - outs("¤p¤Ñ¨Ï§ó·s§¹¦¨¡A¤U¦¸©I¥s®É·|¿ï¥X·sªº¤p¤Ñ¨Ï"); - } - return XEASY; -} - -int t_angelmsg(){ - char msg[3][74] = { "", "", "" }; - char nick[10] = ""; - char buf[512]; - int i; - FILE* fp; - - setuserfile(buf, "angelmsg"); - fp = fopen(buf, "r"); - if (fp) { - i = 0; - if (fgets(msg[0], sizeof(msg[0]), fp)) { - chomp(msg[0]); - if (strncmp(msg[0], "%%[", 3) == 0) { - strlcpy(nick, msg[0] + 3, 7); - move(4, 0); - prints("즳¼ÊºÙ¡G%s", nick); - msg[0][0] = 0; - } else - i = 1; - } else - msg[0][0] = 0; - - move(5, 0); - outs("즳¯d¨¥¡G\n"); - if(msg[0][0]) - outs(msg[0]); - for (; i < 3; ++i) { - if(fgets(msg[i], sizeof(msg[0]), fp)) { - outs(msg[i]); - chomp(msg[i]); - } else - break; - } - fclose(fp); - } - - getdata_buf(11, 0, "¼ÊºÙ¡G", nick, 7, 1); - do { - move(12, 0); - clrtobot(); - outs("¤£¦bªº®ÉÔn¸ò¤p¥D¤H»¡¤°»ò©O¡H" - "³Ì¦h¤T¦æ¡A«ö[Enter]µ²§ô"); - for (i = 0; i < 3 && - getdata_buf(14 + i, 0, "¡G", msg[i], sizeof(msg[i]), DOECHO); - ++i); - getdata(b_lines - 2, 0, "(S)Àx¦s (E)«·s¨Ó¹L (Q)¨ú®ø¡H[S]", - buf, 4, LCECHO); - } while (buf[0] == 'E' || buf[0] == 'e'); - if (buf[0] == 'Q' || buf[0] == 'q') - return 0; - setuserfile(buf, "angelmsg"); - if (msg[0][0] == 0) - unlink(buf); - else { - FILE* fp = fopen(buf, "w"); - if(nick[0]) - fprintf(fp, "%%%%[%s\n", nick); - for (i = 0; i < 3 && msg[i][0]; ++i) { - fputs(msg[i], fp); - fputc('\n', fp); - } - fclose(fp); - } - return 0; -} - -static int -FindAngel(void){ - int nAngel; - int i, j; - int choose; - int trial = 0; - int mask; - - if (cuser.sex < 6) /* ¥¿±`©Ê§O */ - mask = 1 | (2 << (cuser.sex & 1)); - else - mask = 7; - - do{ - nAngel = 0; - j = SHM->currsorted; - for (i = 0; i < SHM->UTMPnumber; ++i) - if ((SHM->uinfo[SHM->sorted[j][0][i]].userlevel & PERM_ANGEL) - && (SHM->uinfo[SHM->sorted[j][0][i]].angel & mask) == 0) - ++nAngel; - - if (nAngel == 0) - return 0; - - choose = random() % nAngel + 1; - j = SHM->currsorted; - for (i = 0; i < SHM->UTMPnumber && choose; ++i) - if ((SHM->uinfo[SHM->sorted[j][0][i]].userlevel & PERM_ANGEL) - && (SHM->uinfo[SHM->sorted[j][0][i]].angel & mask) == 0) - --choose; - - if (choose == 0 && SHM->uinfo[SHM->sorted[j][0][i - 1]].uid != currutmp->uid - && (SHM->uinfo[SHM->sorted[j][0][i - 1]].userlevel & PERM_ANGEL) - && ((SHM->uinfo[SHM->sorted[j][0][i - 1]].angel & mask) == 0) - && !he_reject_me(&SHM->uinfo[SHM->sorted[j][0][i - 1]]) ){ - strlcpy(cuser.myangel, SHM->uinfo[SHM->sorted[j][0][i - 1]].userid, IDLEN + 1); - passwd_update(usernum, &cuser); - return 1; - } - }while(++trial < 5); - return 0; -} - -static inline void -GotoNewHand(){ - char old_board[IDLEN + 1] = ""; - int canRead = 1; - - if (currutmp && currutmp->mode == EDITING) - return; - - // usually crashed as 'assert(currbid == brc_currbid)' - if (currboard[0]) { - strlcpy(old_board, currboard, IDLEN + 1); - currboard = "";// force enter_board - } - - if (enter_board(GLOBAL_NEWBIE) == 0) - canRead = 1; - - if (canRead) - Read(); - - if (canRead && old_board[0]) - enter_board(old_board); -} - - -static inline void -NoAngelFound(const char* msg){ - move(b_lines, 0); - outs(msg); - if (currutmp == NULL || currutmp->mode != EDITING) - outs("¡A½Ð¥ý¦b·s¤âªO¤W´M§äµª®×©Î«ö Ctrl-P µo°Ý"); - clrtoeol(); - refresh(); - sleep(1); - GotoNewHand(); - return; -} - -static inline void -AngelNotOnline(){ - char buf[256]; - const static char* const not_online_message = "±zªº¤p¤Ñ¨Ï²{¦b¤£¦b½u¤W"; - if (cuser.myangel[0] != '-') - sethomefile(buf, cuser.myangel, "angelmsg"); - if (cuser.myangel[0] == '-' || !dashf(buf)) - NoAngelFound(not_online_message); - else { - FILE* fp = fopen(buf, "r"); - clear(); - showtitle("¤p¤Ñ¨Ï¯d¨¥", BBSNAME); - move(4, 0); - clrtobot(); - - buf[0] = 0; - fgets(buf, sizeof(buf), fp); - if (strncmp(buf, "%%[", 3) == 0) { - chomp(buf); - prints("±zªº%s¤p¤Ñ¨Ï²{¦b¤£¦b½u¤W", buf + 3); - fgets(buf, sizeof(buf), fp); - } else - outs(not_online_message); - - outs("\nÍ¢¯d¨¥µ¹§A¡G\n"); - outs(ANSI_COLOR(1;31;44) "¡ó¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t" ANSI_COLOR(37) "" - "¤p¤Ñ¨Ï¯d¨¥" ANSI_COLOR(31) "¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¡ó" ANSI_RESET "\n"); - outs(ANSI_COLOR(1;31) "¢~¢t" ANSI_COLOR(32) " ¤p¤Ñ¨Ï " - " " ANSI_COLOR(31) "¢u¢¡" ANSI_RESET "\n"); - - do { - chomp(buf); - prints(ANSI_COLOR(1;31) "¢x" ANSI_RESET "%-74.74s" ANSI_COLOR(1;31) "¢x" ANSI_RESET "\n", buf); - } while (fgets(buf, sizeof(buf), fp)); - - outs(ANSI_COLOR(1;31) "¢¢¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" - "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¢£" ANSI_RESET "\n"); - outs(ANSI_COLOR(1;31;44) "¡ó¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" - "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¡ó" ANSI_RESET "\n"); - - move(b_lines - 4, 0); - outs("¤p¥D¤H¨Ï¥Î¤W°ÝÃD§ä¤£¨ì¤p¤Ñ¨Ï½Ð¨ì·s¤âª©(" GLOBAL_NEWBIE ")\n" - " ·Q¯d¨¥µ¹¤p¤Ñ¨Ï½Ð¨ì³\\Ä@ª©(AngelPray)\n" - " ·Q§ä¬ÝªO¦bþªº¸Ü¥i¨ì(AskBoard)\n" - "½Ð¥ý¦b¦UªO¤W´M§äµª®×©Î«ö Ctrl-P µo°Ý"); - pressanykey(); - - GotoNewHand(); - } -} - -static void -TalkToAngel(){ - static int AngelPermChecked = 0; - userinfo_t* uent; - userec_t xuser; - - if (strcmp(cuser.myangel, "-") == 0){ - AngelNotOnline(); - return; - } - - if (cuser.myangel[0] && !AngelPermChecked) { - getuser(cuser.myangel, &xuser); // XXX if user doesn't exist - if (!(xuser.userlevel & PERM_ANGEL)) - cuser.myangel[0] = 0; - } - AngelPermChecked = 1; - - if (cuser.myangel[0] == 0 && ! FindAngel()){ - NoAngelFound("²{¦b¨S¦³¤p¤Ñ¨Ï¦b½u¤W"); - return; - } - - uent = search_ulist_userid(cuser.myangel); - if (uent == 0 || (uent->angel & 1) || he_reject_me(uent)){ - AngelNotOnline(); - return; - } - - more("etc/angel_usage", NA); - - /* ³o¬q¸Ü©Î³\¥i¥H¦b¤p¤Ñ¨Ï¦^µª°ÝÃD®É show ¥X¨Ó - move(b_lines - 1, 0); - outs("²{¦b§Aªºid¨ü¨ì«O±K¡A¦^µª§A°ÝÃDªº¤p¤Ñ¨Ï¨Ã¤£ª¾¹D§A¬O½Ö \n" - "§A¥i¥H¿ï¾Ü¤£¦V¹ï¤è³zÅS¦Û¤v¨¥÷¨Ó«OÅ@¦Û¤v "); - */ - - my_write(uent->pid, "°Ý¤p¤Ñ¨Ï¡G ", "¤p¤Ñ¨Ï", WATERBALL_ANGEL, uent); - return; -} - -void -CallAngel(){ - static int entered = 0; - screen_backup_t old_screen; - - if (!HasUserPerm(PERM_LOGINOK) || entered) - return; - entered = 1; - - scr_dump(&old_screen); - - TalkToAngel(); - - scr_restore(&old_screen); - - 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 ? "¥ð®§¤@·|¨à" : "¶}©ñ¤p¥D¤H°Ý°ÝÃD"); - return XEASY; -} -#endif diff --git a/mbbsd/telnet.c b/mbbsd/telnet.c deleted file mode 100644 index 332b3f3a..00000000 --- a/mbbsd/telnet.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * piaip's simplified implementation of TELNET protocol - */ -#ifdef DEBUG -#define TELOPTS -#define TELCMDS -#endif - -#include "bbs.h" - -#ifdef DETECT_CLIENT -void UpdateClientCode(unsigned char c); // see mbbsd.c -#endif - -unsigned int telnet_handler(unsigned char c) ; -void telnet_init(void); -ssize_t tty_read(unsigned char *buf, size_t max); - -enum TELNET_IAC_STATES { - IAC_NONE, - IAC_COMMAND, - IAC_WAIT_OPT, - IAC_WAIT_SE, - IAC_PROCESS_OPT, - IAC_ERROR -}; - -static unsigned char iac_state = 0; /* as byte to reduce memory */ - -#define TELNET_IAC_MAXLEN (16) -/* We don't reply to most commands, so this maxlen can be minimal. - * Warning: if you want to support ENV passing or other long commands, - * remember to increase this value. Howver, some poorly implemented - * terminals like xxMan may not follow the protocols and user will hang - * on those terminals when IACs were sent. - */ - -void -telnet_init(void) -{ - /* We are the boss. We don't respect to client. - * It's client's responsibility to follow us. - * Please write these codes in i-dont-care opt handlers. - */ - const char telnet_init_cmds[] = { - /* retrieve terminal type and throw away. - * why? because without this, clients enter line mode. - */ - IAC, DO, TELOPT_TTYPE, - IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE, - - /* i'm a smart term with resize ability. */ - IAC, DO, TELOPT_NAWS, - - /* i will echo. */ - IAC, WILL, TELOPT_ECHO, - /* supress ga. */ - IAC, WILL, TELOPT_SGA, - /* 8 bit binary. */ - IAC, WILL, TELOPT_BINARY, - IAC, DO, TELOPT_BINARY, - }; - - raw_connection = 1; - write(0, telnet_init_cmds, sizeof(telnet_init_cmds)); -} - -/* tty_read - * read from tty, process telnet commands if raw connection. - * return: >0 = length, <=0 means read more, abort/eof is automatically processed. - */ -ssize_t -tty_read(unsigned char *buf, size_t max) -{ - ssize_t l = read(0, buf, max); - - if(l == 0 || (l < 0 && !(errno == EINTR || errno == EAGAIN))) - abort_bbs(0); - - if(!raw_connection) - return l; - - /* process buffer */ - if (l > 0) { - unsigned char *buf2 = buf; - size_t i = 0, i2 = 0; - - /* prescan. because IAC is rare, - * this cost is worthy. */ - if (iac_state == IAC_NONE && memchr(buf, IAC, l) == NULL) - return l; - - /* we have to look into the buffer. */ - for (i = 0; i < l; i++, buf++) - if(telnet_handler(*buf) == 0) - *(buf2++) = *buf; - else - i2 ++; - l = (i2 == l) ? -1L : l - i2; - } - return l; -} - -#ifdef DBG_OUTRPT -extern unsigned char fakeEscape; -#endif // DBG_OUTRPT - -/* input: raw character - * output: telnet command if c was handled, otherwise zero. - */ -unsigned int -telnet_handler(unsigned char c) -{ - static unsigned char iac_quote = 0; /* as byte to reduce memory */ - static unsigned char iac_opt_req = 0; - - static unsigned char iac_buf[TELNET_IAC_MAXLEN]; - static unsigned int iac_buflen = 0; - - /* we have to quote all IACs. */ - if(c == IAC && !iac_quote) { - iac_quote = 1; - return NOP; - } - -#ifdef DETECT_CLIENT - /* hash client telnet sequences */ - if(cuser.userid[0]==0) { - if(iac_state == IAC_WAIT_SE) { - // skip suboption - } else { - if(iac_quote) - UpdateClientCode(IAC); - UpdateClientCode(c); - } - } -#endif - - /* a special case is the top level iac. otherwise, iac is just a quote. */ - if (iac_quote) { - if(iac_state == IAC_NONE) - iac_state = IAC_COMMAND; - if(iac_state == IAC_WAIT_SE && c == SE) - iac_state = IAC_PROCESS_OPT; - iac_quote = 0; - } - - /* now, let's process commands by state */ - switch(iac_state) { - - case IAC_NONE: - return 0; - - case IAC_COMMAND: -#if 0 // def DEBUG - { - int cx = c; /* to make compiler happy */ - write(0, "-", 1); - if(TELCMD_OK(cx)) - write(0, TELCMD(c), strlen(TELCMD(c))); - write(0, " ", 1); - } -#endif - iac_state = IAC_NONE; /* by default we restore state. */ - switch(c) { - case IAC: - // return 0; - // we don't want to allow IACs as input. - return 1; - - /* we don't want to process these. or maybe in future. */ - case BREAK: /* break */ -#ifdef DBG_OUTRPT - fakeEscape = !fakeEscape; - return NOP; -#endif - - case ABORT: /* Abort process */ - case SUSP: /* Suspend process */ - case AO: /* abort output--but let prog finish */ - case IP: /* interrupt process--permanently */ - case EOR: /* end of record (transparent mode) */ - case DM: /* data mark--for connect. cleaning */ - case xEOF: /* End of file: EOF is already used... */ - return NOP; - - case NOP: /* nop */ - return NOP; - - /* we should process these, but maybe in future. */ - case GA: /* you may reverse the line */ - case EL: /* erase the current line */ - case EC: /* erase the current character */ - return NOP; - - /* good */ - case AYT: /* are you there */ - { - const char *alive = "I'm still alive, loading: "; - char buf[STRLEN]; - - /* respond as fast as we can */ - write(0, alive, strlen(alive)); - cpuload(buf); - write(0, buf, strlen(buf)); - write(0, "\r\n", 2); - } - return NOP; - - case DONT: /* you are not to use option */ - case DO: /* please, you use option */ - case WONT: /* I won't use option */ - case WILL: /* I will use option */ - iac_opt_req = c; - iac_state = IAC_WAIT_OPT; - return NOP; - - case SB: /* interpret as subnegotiation */ - iac_state = IAC_WAIT_SE; - iac_buflen = 0; - return NOP; - - case SE: /* end sub negotiation */ - default: - return NOP; - } - return 1; - - case IAC_WAIT_OPT: -#if 0 // def DEBUG - write(0, "-", 1); - if(TELOPT_OK(c)) - write(0, TELOPT(c), strlen(TELOPT(c))); - write(0, " ", 1); -#endif - iac_state = IAC_NONE; - /* - * According to RFC, there're some tricky steps to prevent loop. - * However because we have a poor term which does not allow - * most abilities, let's be a strong boss here. - * - * Although my old imeplementation worked, it's even better to follow this: - * http://www.tcpipguide.com/free/t_TelnetOptionsandOptionNegotiation-3.htm - */ - switch(c) { - /* i-dont-care: i don't care about what client is. - * these should be clamed in init and - * client must follow me. */ - case TELOPT_TTYPE: /* termtype or line. */ - case TELOPT_NAWS: /* resize terminal */ - case TELOPT_SGA: /* supress GA */ - case TELOPT_ECHO: /* echo */ - case TELOPT_BINARY: /* we are CJK. */ - break; - - /* i-dont-agree: i don't understand/agree these. - * according to RFC, saying NO stopped further - * requests so there'll not be endless loop. */ - case TELOPT_RCP: /* prepare to reconnect */ - default: - if (iac_opt_req == WILL || iac_opt_req == DO) - { - /* unknown option, reply with won't */ - unsigned char cmd[3] = { IAC, DONT, 0 }; - if(iac_opt_req == DO) cmd[1] = WONT; - cmd[2] = c; - write(0, cmd, sizeof(cmd)); - } - break; - } - return 1; - - case IAC_WAIT_SE: - iac_buf[iac_buflen++] = c; - /* no need to convert state because previous quoting will do. */ - - if(iac_buflen == TELNET_IAC_MAXLEN) { - /* may be broken protocol? - * whether finished or not, break for safety - * or user may be frozen. - */ - iac_state = IAC_NONE; - return 0; - } - return 1; - - case IAC_PROCESS_OPT: - iac_state = IAC_NONE; -#if 0 // def DEBUG - write(0, "-", 1); - if(TELOPT_OK(iac_buf[0])) - write(0, TELOPT(iac_buf[0]), strlen(TELOPT(iac_buf[0]))); - write(0, " ", 1); -#endif - switch(iac_buf[0]) { - - /* resize terminal */ - case TELOPT_NAWS: - { - int w = (iac_buf[1] << 8) + (iac_buf[2]); - int h = (iac_buf[3] << 8) + (iac_buf[4]); - term_resize(w, h); -#ifdef DETECT_CLIENT - if(cuser.userid[0]==0) { - UpdateClientCode(iac_buf[0]); - if(w==80 && h==24) - UpdateClientCode(1); - else if(w==80) - UpdateClientCode(2); - else if(h==24) - UpdateClientCode(3); - else - UpdateClientCode(4); - UpdateClientCode(IAC); - UpdateClientCode(SE); - } -#endif - } - break; - - default: -#ifdef DETECT_CLIENT - if(cuser.userid[0]==0) { - int i; - for(i=0;i<iac_buflen;i++) - UpdateClientCode(iac_buf[i]); - UpdateClientCode(IAC); - UpdateClientCode(SE); - } -#endif - break; - } - return 1; - } - return 1; /* never reached */ -} - -// vim: sw=4 diff --git a/mbbsd/term.c b/mbbsd/term.c deleted file mode 100644 index 4868415a..00000000 --- a/mbbsd/term.c +++ /dev/null @@ -1,118 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -/* ----------------------------------------------------- */ -/* basic tty control */ -/* ----------------------------------------------------- */ -void -init_tty(void) -{ - struct termios tty_state, tty_new; - - if (tcgetattr(1, &tty_state) < 0) { - syslog(LOG_ERR, "tcgetattr(): %m"); - return; - } - memcpy(&tty_new, &tty_state, sizeof(tty_new)); - tty_new.c_lflag &= ~(ICANON | ECHO | ISIG); - /* - * tty_new.c_cc[VTIME] = 0; tty_new.c_cc[VMIN] = 1; - */ - tcsetattr(1, TCSANOW, &tty_new); - system("stty raw -echo"); -} - -/* ----------------------------------------------------- */ -/* init tty control code */ -/* ----------------------------------------------------- */ - - -#define TERMCOMSIZE (40) - -static void -sig_term_resize(int sig) -{ - struct winsize newsize; - Signal(SIGWINCH, SIG_IGN); /* Don't bother me! */ - ioctl(0, TIOCGWINSZ, &newsize); - term_resize(newsize.ws_col, newsize.ws_row); -} - -void term_resize(int w, int h) -{ - int dorefresh = 0; - Signal(SIGWINCH, SIG_IGN); /* Don't bother me! */ - - - /* make sure reasonable size */ - h = MAX(24, MIN(100, h)); - w = MAX(80, MIN(200, w)); - - if (w != t_columns || h != t_lines) - { - // invoke terminal system resize - resizeterm(h, w); - - t_lines = h; - t_columns = w; - dorefresh = 1; - } - scr_lns = t_lines; /* XXX: scr_lns ¸ò t_lines ¦³¤°»ò¤£¦P, ¬°¦ó¤À¦¨¨âÓ */ - b_lines = t_lines - 1; - p_lines = t_lines - 4; - - Signal(SIGWINCH, sig_term_resize); - if (dorefresh) - { - redrawwin(); - refresh(); - } -} - -int -term_init(void) -{ - Signal(SIGWINCH, sig_term_resize); - return YEA; -} - -void -do_move(int destcol, int destline) -{ - char buf[16], *p; - - snprintf(buf, sizeof(buf), ANSI_MOVETO(%d,%d), destline + 1, destcol + 1); - for (p = buf; *p; p++) - ochar(*p); -} - -void -save_cursor(void) -{ - ochar(ESC_CHR); - ochar('7'); -} - -void -restore_cursor(void) -{ - ochar(ESC_CHR); - ochar('8'); -} - -void -change_scroll_range(int top, int bottom) -{ - char buf[16], *p; - - snprintf(buf, sizeof(buf), ESC_STR "[%d;%dr", top + 1, bottom + 1); - for (p = buf; *p; p++) - ochar(*p); -} - -void -scroll_forward(void) -{ - ochar(ESC_CHR); - ochar('D'); -} diff --git a/mbbsd/time.c b/mbbsd/time.c deleted file mode 100644 index 11f963c3..00000000 --- a/mbbsd/time.c +++ /dev/null @@ -1,20 +0,0 @@ -#ifdef __dietlibc__ -#include <time.h> -#warning "hardcoded time zone as GMT+8!" -extern void __maplocaltime(void); -extern time_t __tzfile_map(time_t t, int *isdst, int forward); -extern time_t timegm(struct tm *const t); - -time_t mktime(register struct tm* const t) { - time_t x=timegm(t); - x-=8*3600; - return x; -} - -struct tm* localtime_r(const time_t* t, struct tm* r) { - time_t tmp; - tmp=*t; - tmp+=8*3600; - return gmtime_r(&tmp,r); -} -#endif diff --git a/mbbsd/topsong.c b/mbbsd/topsong.c deleted file mode 100644 index 906dadbf..00000000 --- a/mbbsd/topsong.c +++ /dev/null @@ -1,72 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#define MAX_SONGS 300 -#define QCAST int (*)(const void *, const void *) - -typedef struct songcmp_t { - char name[100]; - char cname[100]; - int count; -} songcmp_t; - -static int totalcount = 0; - -static int -count_cmp(songcmp_t * b, songcmp_t * a) -{ - return (a->count - b->count); -} - -int -topsong(void) -{ - more(FN_TOPSONG, YEA); - return 0; -} - - -void -sortsong(void) -{ - FILE *fo, *fp = fopen(BBSHOME "/" FN_USSONG, "r"); - songcmp_t songs[MAX_SONGS + 1]; - int n; - char buf[256], cbuf[256]; - - memset(songs, 0, sizeof(songs)); - if (!fp) - return; - if (!(fo = fopen(FN_TOPSONG, "w"))) { - fclose(fp); - return; - } - totalcount = 0; - /* XXX: °£¤F«e MAX_SONGS º, ³Ñ¤U¤£·|±Æ§Ç */ - while (fgets(buf, 200, fp)) { - chomp(buf); - strip_blank(cbuf, buf); - if (!cbuf[0] || !isprint2((int)cbuf[0])) - continue; - - for (n = 0; n < MAX_SONGS && songs[n].name[0]; n++) - if (!strcmp(songs[n].cname, cbuf)) - break; - strlcpy(songs[n].name, buf, sizeof(songs[n].name)); - strlcpy(songs[n].cname, cbuf, sizeof(songs[n].cname)); - songs[n].count++; - totalcount++; - } - qsort(songs, MAX_SONGS, sizeof(songcmp_t), (QCAST) count_cmp); - fprintf(fo, - " " ANSI_COLOR(36) "¢w¢w" ANSI_COLOR(37) "¦W¦¸" ANSI_COLOR(36) "¢w¢w¢w¢w¢w¢w" ANSI_COLOR(37) "ºq" - " ¦W" ANSI_COLOR(36) "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" ANSI_COLOR(37) "¦¸¼Æ" ANSI_COLOR(36) "" - "¢w¢w" ANSI_COLOR(32) "¦@%d¦¸" ANSI_COLOR(36) "¢w¢w" ANSI_RESET "\n", totalcount); - for (n = 0; n < 100 && songs[n].name[0]; n++) { - fprintf(fo, " %5d. %-38.38s %4d " ANSI_COLOR(32) "[%.2f]" ANSI_RESET "\n", n + 1, - songs[n].name, songs[n].count, - (float)songs[n].count / totalcount); - } - fclose(fp); - fclose(fo); -} diff --git a/mbbsd/user.c b/mbbsd/user.c deleted file mode 100644 index d235d01f..00000000 --- a/mbbsd/user.c +++ /dev/null @@ -1,1452 +0,0 @@ -/* $Id$ */ -#include "bbs.h" -static char * const sex[8] = { - MSG_BIG_BOY, MSG_BIG_GIRL, MSG_LITTLE_BOY, MSG_LITTLE_GIRL, - MSG_MAN, MSG_WOMAN, MSG_PLANT, MSG_MIME -}; - -#ifdef CHESSCOUNTRY -static const char * const chess_photo_name[3] = { - "photo_fivechess", "photo_cchess", "photo_go", -}; - -static const char * const chess_type[3] = { - "¤¤l´Ñ", "¶H´Ñ", "³ò´Ñ", -}; -#endif - -int -kill_user(int num, const char *userid) -{ - userec_t u; - char src[256], dst[256]; - - if(!userid || num<=0 ) return -1; - sethomepath(src, userid); - snprintf(dst, sizeof(dst), "tmp/%s", userid); - friend_delete_all(userid, FRIEND_ALOHA); - delete_allpost(userid); - if (dashd(src) && Rename(src, dst) == 0) { - snprintf(src, sizeof(src), "/bin/rm -fr home/%c/%s >/dev/null 2>&1", userid[0], userid); - system(src); - } - - memset(&u, 0, sizeof(userec_t)); - log_usies("KILL", getuserid(num)); - setuserid(num, ""); - passwd_update(num, &u); - return 0; -} -int -u_loginview(void) -{ - int i, in; - unsigned int pbits = cuser.loginview; - - clear(); - move(4, 0); - for (i = 0; i < NUMVIEWFILE && loginview_file[i][0]; i++) - prints(" %c. %-20s %-15s \n", 'A' + i, - loginview_file[i][1], ((pbits >> i) & 1 ? "£¾" : "¢æ")); - in = i; - - clrtobot(); - while ((i = getkey("½Ð«ö [A-N] ¤Á´«³]©w¡A«ö [Return] µ²§ô¡G"))!='\r') - { - i = i - 'a'; - if (i >= in || i < 0) - bell(); - else { - pbits ^= (1 << i); - move(i + 4, 28); - outs((pbits >> i) & 1 ? "£¾" : "¢æ"); - } - } - - if (pbits != cuser.loginview) { - cuser.loginview = pbits; - passwd_update(usernum, &cuser); - } - return 0; -} -int u_cancelbadpost(void) -{ - int day; - if(cuser.badpost==0) - {vmsg("§A¨Ã¨S¦³¦H¤å."); return 0;} - - if(search_ulistn(usernum,2)) - {vmsg("½Ðµn¥X¨ä¥Lµøµ¡, §_«h¤£¨ü²z."); return 0;} - - passwd_query(usernum, &cuser); - if (currutmp && (currutmp->alerts & ALERT_PWD)) - currutmp->alerts &= ~ALERT_PWD; - - day = 180 - (now - cuser.timeremovebadpost ) / 86400; - if(day>0 && day<=180) - { - vmsgf("¨C 180 ¤Ñ¤~¯à¥Ó½Ð¤@¦¸, ÁÙ³Ñ %d ¤Ñ.", day); - vmsg("±z¤]¥i¥Hª`·N¯¸¤è¬O§_¦³³Ò°ÊªA°È¤è¦¡§R°£¦H¤å."); - return 0; - } - - if( - getkey("§ÚÄ@·N´L¦u¯¸¤è³W©w,²Õ³W,¥H¤ÎªO³W[y/N]?")!='y' || - getkey("§ÚÄ@·N´L«¤£ª[µø±Ú¸s,¤£¾xªO,´L«¦UªO¥DÅv¤O[y/N]?")!='y' || - getkey("§ÚÄ@·NÂÔ·Vµoªí¦³·N¸q¨¥½×,¤£ðã½|§ðÀ»,¤£¸óªO¼s§i[y/N]?")!='y' ) - - {vmsg("½Ð±z«ä¦Ò²M·¡«á¦A¨Ó¥Ó½Ð§R°£."); return 0;} - - if(search_ulistn(usernum,2)) - {vmsg("½Ðµn¥X¨ä¥Lµøµ¡, §_«h¤£¨ü²z."); return 0;} - if(cuser.badpost) - { - int prev = cuser.badpost--; - cuser.timeremovebadpost = now; - passwd_update(usernum, &cuser); - log_filef("log/cancelbadpost.log", LOG_CREAT, - "%s %s §R°£¤@½g¦H¤å (%d -> %d ½g)\n", - Cdate(&now), cuser.userid, prev, cuser.badpost); - } - vmsg("®¥³ß±z¤w¸g¦¨¥\\§R°£¤@½g¦H¤å."); - return 0; -} - -void -user_display(const userec_t * u, int adminmode) -{ - int diff = 0; - char genbuf[200]; - - clrtobot(); - prints( - " " ANSI_COLOR(30;41) "¢r¢s¢r¢s¢r¢s" ANSI_RESET " " ANSI_COLOR(1;30;45) " ¨Ï ¥Î ªÌ" - " ¸ê ®Æ " - " " ANSI_RESET " " ANSI_COLOR(30;41) "¢r¢s¢r¢s¢r¢s" ANSI_RESET "\n"); - prints(" ¥N¸¹¼ÊºÙ: %s(%s)\n" - " ¯u¹ê©m¦W: %s" -#if FOREIGN_REG_DAY > 0 - " %s%s" -#elif defined(FOREIGN_REG) - " %s" -#endif - "\n" - " ©~¦í¦í§}: %s\n" - " ¹q¤l«H½c: %s\n" - " ©Ê §O: %s\n" - " »È¦æ±b¤á: %d »È¨â\n", - u->userid, u->nickname, u->realname, -#if FOREIGN_REG_DAY > 0 - u->uflag2 & FOREIGN ? "(¥~Äy: " : "", - u->uflag2 & FOREIGN ? - (u->uflag2 & LIVERIGHT) ? "¥Ã¤[©~¯d)" : "¥¼¨ú±o©~¯dÅv)" - : "", -#elif defined(FOREIGN_REG) - u->uflag2 & FOREIGN ? "(¥~Äy)" : "", -#endif - u->address, u->email, - sex[u->sex % 8], u->money); - - sethomedir(genbuf, u->userid); - prints(" ¨p¤H«H½c: %d «Ê (ÁʶR«H½c: %d «Ê)\n" - " ¤â¾÷¸¹½X: %010d\n" - " ¥Í ¤é: %04i/%02i/%02i (%sº¡18·³)\n", - get_num_records(genbuf, sizeof(fileheader_t)), - u->exmailbox, u->mobile, - u->year + 1900, u->month, u->day, over18 ? "¤w" : "¥¼" - ); - -#ifdef ASSESS - prints(" Àu ¦H ¤å: Àu:%d / ¦H:%d\n", - u->goodpost, u->badpost); -#endif // ASSESS - - prints(" ¤W¯¸¦ì¸m: %s\n", u->lasthost); - -#ifdef PLAY_ANGEL - if (adminmode) - prints(" ¤p ¤Ñ ¨Ï: %s\n", - u->myangel[0] ? u->myangel : "µL"); -#endif - prints(" µù¥U¤é´Á: %s", ctime4(&u->firstlogin)); - prints(" «e¦¸¥úÁ{: %s", ctime4(&u->lastlogin)); - prints(" ¤W¯¸¤å³¹: %d ¦¸ / %d ½g\n", - u->numlogins, u->numposts); - -#ifdef CHESSCOUNTRY - { - int i, j; - FILE* fp; - for(i = 0; i < 2; ++i){ - sethomefile(genbuf, u->userid, chess_photo_name[i]); - fp = fopen(genbuf, "r"); - if(fp != NULL){ - for(j = 0; j < 11; ++j) - fgets(genbuf, 200, fp); - fgets(genbuf, 200, fp); - prints("%12s´Ñ°ê¦Û§Ú´yz: %s", chess_type[i], genbuf + 11); - fclose(fp); - } - } - } -#endif - - if (adminmode) { - strcpy(genbuf, "bTCPRp#@XWBA#VSM0123456789ABCDEF"); - for (diff = 0; diff < 32; diff++) - if (!(u->userlevel & (1 << diff))) - genbuf[diff] = '-'; - prints(" »{ÃÒ¸ê®Æ: %s\n" - " userÅv: %s\n", - u->justify, genbuf); - } else { - diff = (now - login_start_time) / 60; - prints(" °±¯d´Á¶¡: %d ¤p®É %2d ¤À\n", - diff / 60, diff % 60); - } - - /* Thor: ·Q¬Ý¬Ý³oÓ user ¬O¨º¨ÇªOªºªO¥D */ - if (u->userlevel >= PERM_BM) { - int i; - boardheader_t *bhdr; - - outs(" ¾á¥ôªO¥D: "); - - for (i = 0, bhdr = bcache; i < numboards; i++, bhdr++) { - if (is_uBM(bhdr->BM, u->userid)) { - outs(bhdr->brdname); - outc(' '); - } - } - outc('\n'); - } - outs(" " ANSI_COLOR(30;41) "¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r¢s¢r" - "¢s¢r¢s¢r¢s¢r¢s" ANSI_RESET); - - outs((u->userlevel & PERM_LOGINOK) ? - "\n±zªºµù¥Uµ{§Ç¤w¸g§¹¦¨¡AÅwªï¥[¤J¥»¯¸" : - "\n¦pªGn´£ª@Åv¡A½Ð°Ñ¦Ò¥»¯¸¤½§GÄæ¿ì²zµù¥U"); - -#ifdef NEWUSER_LIMIT - if ((u->lastlogin - u->firstlogin < 3 * 86400) && !HasUserPerm(PERM_POST)) - outs("\n·s¤â¤W¸ô¡A¤T¤Ñ«á¶}©ñÅv"); -#endif -} - -void -mail_violatelaw(const char *crime, const char *police, const char *reason, const char *result) -{ - char genbuf[200]; - fileheader_t fhdr; - FILE *fp; - - sendalert(crime, ALERT_PWD_PERM); - - sethomepath(genbuf, crime); - stampfile(genbuf, &fhdr); - if (!(fp = fopen(genbuf, "w"))) - return; - fprintf(fp, "§@ªÌ: [" BBSMNAME "ĵ¹î§½]\n" - "¼ÐÃD: [³ø§i] ¹Hªk³ø§i\n" - "®É¶¡: %s\n" - ANSI_COLOR(1;32) "%s" ANSI_RESET "§P¨M¡G\n " ANSI_COLOR(1;32) "%s" ANSI_RESET - "¦]" ANSI_COLOR(1;35) "%s" ANSI_RESET "¦æ¬°¡A\n" - "¹H¤Ï¥»¯¸¯¸³W¡A³B¥H" ANSI_COLOR(1;35) "%s" ANSI_RESET "¡A¯S¦¹³qª¾\n\n" - "½Ð¨ì " GLOBAL_LAW " ¬d¸ß¬ÛÃöªk³W¸ê°T¡A¨Ã±q¥D¿ï³æ¶i¤J:\n" - "(P)lay¡i®T¼Ö»P¥ð¶¢¡j=>(P)ay¡i¢Þtt¶q³c©± ¡j=> (1)ViolateLaw ú»@³æ\n" - "¥Hú¥æ»@³æ¡C\n", - ctime4(&now), police, crime, reason, result); - fclose(fp); - strcpy(fhdr.title, "[³ø§i] ¹Hªk§P¨M³ø§i"); - strcpy(fhdr.owner, "[" BBSMNAME "ĵ¹î§½]"); - sethomedir(genbuf, crime); - append_record(genbuf, &fhdr, sizeof(fhdr)); -} - -void -kick_all(char *user) -{ - userinfo_t *ui; - int num = searchuser(user, NULL), i=1; - while((ui = (userinfo_t *) search_ulistn(num, i)) != NULL) - { - if(ui == currutmp) i++; - if ((ui->pid <= 0 || kill(ui->pid, SIGHUP) == -1)) - purge_utmp(ui); - log_usies("KICK ALL", user); - } -} - -void -violate_law(userec_t * u, int unum) -{ - char ans[4], ans2[4]; - char reason[128]; - move(1, 0); - clrtobot(); - move(2, 0); - outs("(1)Cross-post (2)¶Ãµo¼s§i«H (3)¶Ãµo³sÂê«H\n"); - outs("(4)ÄÌÂZ¯¸¤W¨Ï¥ÎªÌ (8)¨ä¥L¥H»@³æ³B¸m¦æ¬°\n(9)¬å id ¦æ¬°\n"); - getdata(5, 0, "(0)µ²§ô", ans, 3, DOECHO); - switch (ans[0]) { - case '1': - strcpy(reason, "Cross-post"); - break; - case '2': - strcpy(reason, "¶Ãµo¼s§i«H"); - break; - case '3': - strcpy(reason, "¶Ãµo³sÂê«H"); - break; - case '4': - while (!getdata(7, 0, "½Ð¿é¤J³QÀËÁ|²z¥Ñ¥H¥Üt³d¡G", reason, 50, DOECHO)); - strcat(reason, "[ÄÌÂZ¯¸¤W¨Ï¥ÎªÌ]"); - break; - case '8': - case '9': - while (!getdata(6, 0, "½Ð¿é¤J²z¥Ñ¥H¥Üt³d¡G", reason, 50, DOECHO)); - break; - default: - return; - } - getdata(7, 0, msg_sure_ny, ans2, 3, LCECHO); - if (*ans2 != 'y') - return; - if (ans[0] == '9') { - if (HasUserPerm(PERM_POLICE) && (u->numlogins > 100 || u->numposts > 100)) - return; - - kill_user(unum, u->userid); - post_violatelaw(u->userid, cuser.userid, reason, "¬å°£ ID"); - } else { - kick_all(u->userid); - u->userlevel |= PERM_VIOLATELAW; - u->timeviolatelaw = now; - u->vl_count++; - passwd_update(unum, u); - post_violatelaw(u->userid, cuser.userid, reason, "»@³æ³B¥÷"); - mail_violatelaw(u->userid, "¯¸°Èĵ¹î", reason, "»@³æ³B¥÷"); - } - pressanykey(); -} - -void Customize(void) -{ - char done = 0; - int dirty = 0; - int key; - - /* cuser.uflag settings */ - static const unsigned int masks1[] = { - MOVIE_FLAG, - NO_MODMARK_FLAG , - COLORED_MODMARK, -#ifdef DBCSAWARE - DBCSAWARE_FLAG, - DBCS_NOINTRESC, -#endif - DEFBACKUP_FLAG, - 0, - }; - - static const char* desc1[] = { - "°ÊºA¬ÝªO", - "ÁôÂä峹קï²Å¸¹(±À¤å/פå) (~)", - "§ï¥Î¦â±m¥N´Àקï²Å¸¹ (+)", -#ifdef DBCSAWARE - "¦Û°Ê°»´úÂù¦ì¤¸¦r¶°(¦p¥þ«¬¤¤¤å)", - "¸T¤î¦bÂù¦ì¤¸¤¤¨Ï¥Î¦â½X(¥h¤@¦rÂù¦â)", -#endif - "¹w³]³Æ¥÷«H¥ó»P¨ä¥¦°O¿ý", //"»P²á¤Ñ°O¿ý", - 0, - }; - - /* cuser.uflag2 settings */ - static const unsigned int masks2[] = { - REJ_OUTTAMAIL, - FAVNEW_FLAG, - FAVNOHILIGHT, - 0, - }; - - static const char* desc2[] = { - "©Ú¦¬¯¸¥~«H", - "·sªO¦Û°Ê¶i§Úªº³Ì·R", - "³æ¦âÅã¥Ü§Úªº³Ì·R", - 0, - }; - - while ( !done ) { - int i = 0, ia = 0, ic = 0; /* general uflags */ - int iax = 0; /* extended flags */ - - clear(); - showtitle("Ó¤H¤Æ³]©w", "Ó¤H¤Æ³]©w"); - move(2, 0); - outs("±z¥Ø«eªºÓ¤H¤Æ³]©w: "); - move(4, 0); - - /* print uflag options */ - for (i = 0; masks1[i]; i++, ia++) - { - clrtoeol(); - prints( ANSI_COLOR(1;36) "%c" ANSI_RESET - ". %-40s%s\n", - 'a' + ia, desc1[i], - (cuser.uflag & masks1[i]) ? - ANSI_COLOR(1;36) "¬O" ANSI_RESET : "§_"); - } - ic = i; - /* print uflag2 options */ - for (i = 0; masks2[i]; i++, ia++) - { - clrtoeol(); - prints( ANSI_COLOR(1;36) "%c" ANSI_RESET - ". %-40s%s" ANSI_RESET "\n", - 'a' + ia, desc2[i], - (cuser.uflag2 & masks2[i]) ? - ANSI_COLOR(1;36) "¬O" ANSI_RESET : "§_"); - } - /* extended stuff */ - { - char mindbuf[5]; - static const char *wm[] = - {"¤@¯ë", "¶i¶¥", "¥¼¨Ó", ""}; - - prints("%c. %-40s%s\n", - '1' + iax++, - "¤ô²y¼Ò¦¡", - wm[(cuser.uflag2 & WATER_MASK)]); - memcpy(mindbuf, &currutmp->mind, 4); - mindbuf[4] = 0; - prints("%c. %-40s%s\n", - '1' + iax++, - "¥Ø«eªº¤ß±¡", - mindbuf); -#ifdef PLAY_ANGEL - /* damn it, dirty stuff here */ - if( HasUserPerm(PERM_ANGEL) ) - { - const char *am[4] = - {"¨k¤k¬Ò¥i", "¤k¥Í", "¨k¥Í", "¼È¤£±µ¨ü·sªº¤p¥D¤H"}; - prints("%c. %-40s%10s\n", - '1' + iax++, - "¶}©ñ¤p¥D¤H¸ß°Ý", - (REJECT_QUESTION ? "§_" : "¬O")); - prints("%c. %-40s%10s\n", - '1' + iax++, - "±µ¨üªº¤p¥D¤H©Ê§O", - am[ANGEL_STATUS()]); - } -#endif - } - - /* input */ - key = getkey("½Ð«ö [a-%c,1-%c] ¤Á´«³]©w¡A¨ä¥¦¥ô·NÁäµ²§ô: ", - 'a' + ia-1, '1' + iax -1); - - if (key >= 'a' && key < 'a' + ia) - { - /* normal pref */ - key -= 'a'; - dirty = 1; - - if(key < ic) - { - cuser.uflag ^= masks1[key]; - } else { - key -= ic; - cuser.uflag2 ^= masks2[key]; - } - continue; - } - - if (key < '1' || key >= '1' + iax) - { - done = 1; continue; - } - /* extended keys */ - key -= '1'; - - switch(key) - { - case 0: - { - int currentset = cuser.uflag2 & WATER_MASK; - currentset = (currentset + 1) % 3; - cuser.uflag2 &= ~WATER_MASK; - cuser.uflag2 |= currentset; - vmsg("×¥¿¤ô²y¼Ò¦¡«á½Ð¥¿±`Â÷½u¦A«·s¤W½u"); - dirty = 1; - } - continue; - case 1: - { - char mindbuf[6] = ""; - getdata(b_lines - 1, 0, "²{¦bªº¤ß±¡? ", - mindbuf, 5, DOECHO); - if (strcmp(mindbuf, "³q½r") == 0) - vmsg("¤£¥i¥H§â¦Û¤v³]³q½r°Õ!"); - else if (strcmp(mindbuf, "¹Ø¬P") == 0) - vmsg("§A¤£¬O¤µ¤Ñ¥Í¤éÕÙ!"); - else - memcpy(currutmp->mind, mindbuf, 4); - dirty = 1; - } - continue; - } -#ifdef PLAY_ANGEL - if( HasUserPerm(PERM_ANGEL) ){ - if (key == iax-2) - { - SwitchBeingAngel(); - dirty = 1; continue; - } - else if (key == iax-1) - { - SwitchAngelSex(ANGEL_STATUS() + 1); - dirty = 1; continue; - } - } -#endif - - } - - grayout(1, b_lines-2, GRAYOUT_DARK); - move(b_lines-1, 0); clrtoeol(); - - if(dirty) - { - passwd_update(usernum, &cuser); - outs("³]©w¤wÀx¦s¡C\n"); - } else { - outs("µ²§ô³]©w¡C\n"); - } - - redrawwin(); // in case we changed output pref (like DBCS) - vmsg("³]©w§¹¦¨"); -} - - -void -uinfo_query(userec_t *u, int adminmode, int unum) -{ - userec_t x; - int i = 0, fail; - int ans; - char buf[STRLEN]; - char genbuf[200]; - int y = 0; - int perm_changed; - int mail_changed; - int money_changed; - int tokill = 0; - int changefrom = 0; - - fail = 0; - mail_changed = money_changed = perm_changed = 0; - - { - // verify unum - int xuid = getuser(u->userid, &x); - if (xuid != unum) - { - vmsg("¨t²Î¿ù»~: ¨Ï¥ÎªÌ¸ê®Æ¸¹½X (unum) ¤£¦X¡C½Ð¦Ü " GLOBAL_BUGREPORT "³ø§i¡C"); - return; - } - } - - memcpy(&x, u, sizeof(userec_t)); - ans = getans(adminmode ? - "(1)§ï¸ê®Æ(2)±K½X(3)Åv(4)¬å±b¸¹(5)§ïID(6)Ãdª«(7)¼f§P(M)«H½c [0]µ²§ô " : - "½Ð¿ï¾Ü (1)קï¸ê®Æ (2)³]©w±K½X (M)קï«H½c (C) Ó¤H¤Æ³]©w ==> [0]µ²§ô "); - - if (ans > '2' && ans != 'm' && ans != 'c' && !adminmode) - ans = '0'; - - if (ans == '1' || ans == '3' || ans == 'm') { - clear(); - y = 1; - move(y++, 0); - outs(msg_uid); - outs(x.userid); - } - switch (ans) { - case 'c': - Customize(); - return; - - case 'm': - do { - getdata_str(y, 0, "¹q¤l«H½c [ÅÜ°Ên«·s»{ÃÒ]¡G", buf, - sizeof(x.email), DOECHO, x.email); - // TODO ³o¸Ì¤]n emaildb_check -#ifdef USE_EMAILDB - if (isvalidemail(buf)) - { - int email_count = emaildb_check_email(buf, strlen(buf)); - if (email_count < 0) - vmsg("¼È®É¤£¤¹³\\ email »{ÃÒ, ½Ðµy«á¦A¸Õ"); - else if (email_count >= EMAILDB_LIMIT) - vmsg("«ü©wªº E-Mail ¤wµù¥U¹L¦h±b¸¹, ½Ð¨Ï¥Î¨ä¥L E-Mail"); - else // valid - break; - } - continue; -#endif - } while (!isvalidemail(buf) && vmsg("»{ÃÒ«H½c¤£¯à¥Î¨Ï¥Î§K¶O«H½c")); - y++; - // admins may want to use special names - if (strcmp(buf, x.email) && - (strchr(buf, '@') || adminmode)) { - - // TODO ³o¸Ì¤]n emaildb_check -#ifdef USE_EMAILDB - if (emaildb_update_email(cuser.userid, strlen(cuser.userid), - buf, strlen(buf)) < 0) { - vmsg("¼È®É¤£¤¹³\\ email »{ÃÒ, ½Ðµy«á¦A¸Õ"); - break; - } -#endif - strlcpy(x.email, buf, sizeof(x.email)); - mail_changed = 1; - delregcodefile(); - } - break; - - case '7': - violate_law(&x, unum); - return; - case '1': - move(0, 0); - outs("½Ð³v¶µ×§ï¡C"); - - getdata_buf(y++, 0, " ¼Ê ºÙ ¡G", x.nickname, - sizeof(x.nickname), DOECHO); - if (adminmode) { - getdata_buf(y++, 0, "¯u¹ê©m¦W¡G", - x.realname, sizeof(x.realname), DOECHO); - getdata_buf(y++, 0, "©~¦í¦a§}¡G", - x.address, sizeof(x.address), DOECHO); - } - buf[0] = 0; - if (x.mobile) - snprintf(buf, sizeof(buf), "%010d", x.mobile); - getdata_buf(y++, 0, "¤â¾÷¸¹½X¡G", buf, 11, LCECHO); - x.mobile = atoi(buf); - snprintf(genbuf, sizeof(genbuf), "%d", (u->sex + 1) % 8); - getdata_str(y++, 0, "©Ê§O (1)¸¯®æ (2)©j±µ (3)©³} (4)¬ü¬Ü (5)Á¦¨û " - "(6)ªü«¼ (7)´Óª« (8)Äqª«¡G", - buf, 3, DOECHO, genbuf); - if (buf[0] >= '1' && buf[0] <= '8') - x.sex = (buf[0] - '1') % 8; - else - x.sex = u->sex % 8; - - while (1) { - snprintf(genbuf, sizeof(genbuf), "%04i/%02i/%02i", - u->year + 1900, u->month, u->day); - if (getdata_str(y, 0, "¥Í¤é ¦è¤¸/¤ë¤ë/¤é¤é¡G", buf, 11, DOECHO, genbuf) == 0) { - x.month = u->month; - x.day = u->day; - x.year = u->year; - } else { - int y, m, d; - if (ParseDate(buf, &y, &m, &d)) - continue; - x.month = (unsigned char)m; - x.day = (unsigned char)d; - x.year = (unsigned char)(y - 1900); - } - if (!adminmode && x.year < 40) - continue; - y++; - break; - } - -#ifdef PLAY_ANGEL - if (adminmode) { - const char* prompt; - userec_t the_angel; - if (x.myangel[0] == 0 || x.myangel[0] == '-' || - (getuser(x.myangel, &the_angel) && - the_angel.userlevel & PERM_ANGEL)) - prompt = "¤p¤Ñ¨Ï¡G"; - else - prompt = "¤p¤Ñ¨Ï¡]¦¹±b¸¹¤wµL¤p¤Ñ¨Ï¸ê®æ¡^¡G"; - while (1) { - userec_t xuser; - getdata_str(y, 0, prompt, buf, IDLEN + 1, DOECHO, - x.myangel); - if(buf[0] == 0 || strcmp(buf, "-") == 0 || - (getuser(buf, &xuser) && - (xuser.userlevel & PERM_ANGEL)) || - strcmp(x.myangel, buf) == 0){ - strlcpy(x.myangel, xuser.userid, IDLEN + 1); - ++y; - break; - } - - prompt = "¤p¤Ñ¨Ï¡G"; - } - } -#endif - -#ifdef CHESSCOUNTRY - { - int j, k; - FILE* fp; - for(j = 0; j < 2; ++j){ - sethomefile(genbuf, u->userid, chess_photo_name[j]); - fp = fopen(genbuf, "r"); - if(fp != NULL){ - FILE* newfp; - char mybuf[200]; - for(k = 0; k < 11; ++k) - fgets(genbuf, 200, fp); - fgets(genbuf, 200, fp); - chomp(genbuf); - - snprintf(mybuf, 200, "%s´Ñ°ê¦Û§Ú´yz¡G", chess_type[j]); - getdata_buf(y, 0, mybuf, genbuf + 11, 80 - 11, DOECHO); - ++y; - - sethomefile(mybuf, u->userid, chess_photo_name[j]); - strcat(mybuf, ".new"); - if((newfp = fopen(mybuf, "w")) != NULL){ - rewind(fp); - for(k = 0; k < 11; ++k){ - fgets(mybuf, 200, fp); - fputs(mybuf, newfp); - } - fputs(genbuf, newfp); - fputc('\n', newfp); - - fclose(newfp); - - sethomefile(genbuf, u->userid, chess_photo_name[j]); - sethomefile(mybuf, u->userid, chess_photo_name[j]); - strcat(mybuf, ".new"); - - Rename(mybuf, genbuf); - } - fclose(fp); - } - } - } -#endif - - if (adminmode) { - int tmp; - if (HasUserPerm(PERM_BBSADM)) { - snprintf(genbuf, sizeof(genbuf), "%d", x.money); - if (getdata_str(y++, 0, "»È¦æ±b¤á¡G", buf, 10, DOECHO, genbuf)) - if ((tmp = atol(buf)) != 0) { - if (tmp != x.money) { - money_changed = 1; - changefrom = x.money; - x.money = tmp; - } - } - } - snprintf(genbuf, sizeof(genbuf), "%d", x.exmailbox); - if (getdata_str(y++, 0, "ÁʶR«H½c¼Æ¡G", buf, 6, - DOECHO, genbuf)) - if ((tmp = atoi(buf)) != 0) - x.exmailbox = (int)tmp; - - getdata_buf(y++, 0, "»{ÃÒ¸ê®Æ¡G", x.justify, - sizeof(x.justify), DOECHO); - getdata_buf(y++, 0, "³Ìªñ¥úÁ{¾÷¾¹¡G", - x.lasthost, sizeof(x.lasthost), DOECHO); - - snprintf(genbuf, sizeof(genbuf), "%d", x.numlogins); - if (getdata_str(y++, 0, "¤W½u¦¸¼Æ¡G", buf, 10, DOECHO, genbuf)) - if ((tmp = atoi(buf)) >= 0) - x.numlogins = tmp; - snprintf(genbuf, sizeof(genbuf), "%d", u->numposts); - if (getdata_str(y++, 0, "¤å³¹¼Æ¥Ø¡G", buf, 10, DOECHO, genbuf)) - if ((tmp = atoi(buf)) >= 0) - x.numposts = tmp; - snprintf(genbuf, sizeof(genbuf), "%d", u->goodpost); - if (getdata_str(y++, 0, "Àu¨}¤å³¹¼Æ:", buf, 10, DOECHO, genbuf)) - if ((tmp = atoi(buf)) >= 0) - x.goodpost = tmp; - snprintf(genbuf, sizeof(genbuf), "%d", u->badpost); - if (getdata_str(y++, 0, "´c¦H¤å³¹¼Æ:", buf, 10, DOECHO, genbuf)) - if ((tmp = atoi(buf)) >= 0) - x.badpost = tmp; - snprintf(genbuf, sizeof(genbuf), "%d", u->vl_count); - if (getdata_str(y++, 0, "¹Hªk°O¿ý¡G", buf, 10, DOECHO, genbuf)) - if ((tmp = atoi(buf)) >= 0) - x.vl_count = tmp; - - snprintf(genbuf, sizeof(genbuf), - "%d/%d/%d", u->five_win, u->five_lose, u->five_tie); - if (getdata_str(y++, 0, "¤¤l´Ñ¾ÔÁZ ³Ó/±Ñ/©M¡G", buf, 16, DOECHO, - genbuf)) - while (1) { - char *p; - char *strtok_pos; - p = strtok_r(buf, "/\r\n", &strtok_pos); - if (!p) - break; - x.five_win = atoi(p); - p = strtok_r(NULL, "/\r\n", &strtok_pos); - if (!p) - break; - x.five_lose = atoi(p); - p = strtok_r(NULL, "/\r\n", &strtok_pos); - if (!p) - break; - x.five_tie = atoi(p); - break; - } - snprintf(genbuf, sizeof(genbuf), - "%d/%d/%d", u->chc_win, u->chc_lose, u->chc_tie); - if (getdata_str(y++, 0, "¶H´Ñ¾ÔÁZ ³Ó/±Ñ/©M¡G", buf, 16, DOECHO, - genbuf)) - while (1) { - char *p; - char *strtok_pos; - p = strtok_r(buf, "/\r\n", &strtok_pos); - if (!p) - break; - x.chc_win = atoi(p); - p = strtok_r(NULL, "/\r\n", &strtok_pos); - if (!p) - break; - x.chc_lose = atoi(p); - p = strtok_r(NULL, "/\r\n", &strtok_pos); - if (!p) - break; - x.chc_tie = atoi(p); - break; - } -#ifdef FOREIGN_REG - if (getdata_str(y++, 0, "¦í¦b 1)¥xÆW 2)¨ä¥L¡G", buf, 2, DOECHO, x.uflag2 & FOREIGN ? "2" : "1")) - if ((tmp = atoi(buf)) > 0){ - if (tmp == 2){ - x.uflag2 |= FOREIGN; - } - else - x.uflag2 &= ~FOREIGN; - } - if (x.uflag2 & FOREIGN) - if (getdata_str(y++, 0, "¥Ã¤[©~¯dÅv 1)¬O 2)§_¡G", buf, 2, DOECHO, x.uflag2 & LIVERIGHT ? "1" : "2")){ - if ((tmp = atoi(buf)) > 0){ - if (tmp == 1){ - x.uflag2 |= LIVERIGHT; - x.userlevel |= (PERM_LOGINOK | PERM_POST); - } - else{ - x.uflag2 &= ~LIVERIGHT; - x.userlevel &= ~(PERM_LOGINOK | PERM_POST); - } - } - } -#endif - } - break; - - case '2': - y = 19; - if (!adminmode) { - if (!getdata(y++, 0, "½Ð¿é¤Jì±K½X¡G", buf, PASSLEN, NOECHO) || - !checkpasswd(u->passwd, buf)) { - outs("\n\n±z¿é¤Jªº±K½X¤£¥¿½T\n"); - fail++; - break; - } - } else { - FILE *fp; - char witness[3][32], title[100]; - int uid; - for (i = 0; i < 3; i++) { - if (!getdata(19 + i, 0, "½Ð¿é¤J¨ó§UÃÒ©ú¤§¨Ï¥ÎªÌ¡G", - witness[i], sizeof(witness[i]), DOECHO)) { - outs("\n¤£¿é¤J«hµLªk§ó§ï\n"); - fail++; - break; - } else if (!(uid = searchuser(witness[i], NULL))) { - outs("\n¬dµL¦¹¨Ï¥ÎªÌ\n"); - fail++; - break; - } else { - userec_t atuser; - passwd_query(uid, &atuser); - if (now - atuser.firstlogin < 6 * 30 * 24 * 60 * 60) { - outs("\nµù¥U¥¼¶W¹L¥b¦~¡A½Ð«·s¿é¤J\n"); - i--; - } - strcpy(witness[i], atuser.userid); - // Adjust upper or lower case - } - } - if (i < 3) - break; - - sprintf(title, "%s ªº±K½X«³]³qª¾ (by %s)",u->userid, cuser.userid); - unlink("etc/updatepwd.log"); - if(! (fp = fopen("etc/updatepwd.log", "w"))) - break; - - fprintf(fp, "%s n¨D±K½X«³]:\n" - "¨£ÃÒ¤H¬° %s, %s, %s", - u->userid, witness[0], witness[1], witness[2] ); - fclose(fp); - - post_file(GLOBAL_SECURITY, title, "etc/updatepwd.log", "[¨t²Î¦w¥þ§½]"); - mail_id(u->userid, title, "etc/updatepwd.log", cuser.userid); - for(i=0; i<3; i++) - { - mail_id(witness[i], title, "etc/updatepwd.log", cuser.userid); - } - y = 20; - } - - if (!getdata(y++, 0, "½Ð³]©w·s±K½X¡G", buf, PASSLEN, NOECHO)) { - outs("\n\n±K½X³]©w¨ú®ø, Ä~Äò¨Ï¥Î±K½X\n"); - fail++; - break; - } - strlcpy(genbuf, buf, PASSLEN); - - move(y+1, 0); - outs("½Ðª`·N³]©w±K½X¥u¦³«e¤KÓ¦r¤¸¦³®Ä¡A¶W¹Lªº±N¦Û°Ê©¿²¤¡C"); - - getdata(y++, 0, "½ÐÀˬd·s±K½X¡G", buf, PASSLEN, NOECHO); - if (strncmp(buf, genbuf, PASSLEN)) { - outs("\n\n·s±K½X½T»{¥¢±Ñ, µLªk³]©w·s±K½X\n"); - fail++; - break; - } - buf[8] = '\0'; - strlcpy(x.passwd, genpasswd(buf), sizeof(x.passwd)); - break; - - case '3': - { - int tmp = setperms(x.userlevel, str_permid); - if (tmp == x.userlevel) - fail++; - else { - perm_changed = 1; - changefrom = x.userlevel; - x.userlevel = tmp; - } - } - break; - - case '4': - tokill = 1; - break; - - case '5': - if (getdata_str(b_lines - 3, 0, "·sªº¨Ï¥ÎªÌ¥N¸¹¡G", genbuf, IDLEN + 1, - DOECHO, x.userid)) { - if (searchuser(genbuf, NULL)) { - outs("¿ù»~! ¤w¸g¦³¦P¼Ë ID ªº¨Ï¥ÎªÌ"); - fail++; - } else - strlcpy(x.userid, genbuf, sizeof(x.userid)); - } - break; - case '6': - chicken_toggle_death(x.userid); - break; - default: - return; - } - - if (fail) { - pressanykey(); - return; - } - if (getans(msg_sure_ny) == 'y') { - if (perm_changed) { - post_change_perm(changefrom, x.userlevel, cuser.userid, x.userid); -#ifdef PLAY_ANGEL - if (x.userlevel & ~changefrom & PERM_ANGEL) - mail_id(x.userid, "¯Í»Hªø¥X¨Ó¤F¡I", "etc/angel_notify", "[¤W«Ò]"); -#endif - } - if (strcmp(u->userid, x.userid)) { - char src[STRLEN], dst[STRLEN]; - - sethomepath(src, u->userid); - sethomepath(dst, x.userid); - Rename(src, dst); - setuserid(unum, x.userid); - } - if (mail_changed && !adminmode) { - // wait registration. - x.userlevel &= ~(PERM_LOGINOK | PERM_POST); - } - memcpy(u, &x, sizeof(x)); - if (tokill) { - kill_user(unum, x.userid); - return; - } else - log_usies("SetUser", x.userid); - if (money_changed) { - char title[TTLEN+1]; - char msg[200]; - char reason[50]; - clrtobot(); - clear(); - while (!getdata(5, 0, "½Ð¿é¤J²z¥Ñ¥H¥Üt³d¡G", - reason, sizeof(reason), DOECHO)); - - snprintf(msg, sizeof(msg), - " ¯¸ªø" ANSI_COLOR(1;32) "%s" ANSI_RESET "§â" ANSI_COLOR(1;32) "%s" ANSI_RESET "ªº¿ú" - "±q" ANSI_COLOR(1;35) "%d" ANSI_RESET "§ï¦¨" ANSI_COLOR(1;35) "%d" ANSI_RESET "\n" - " " ANSI_COLOR(1;37) "¯¸ªø%sקï¿ú²z¥Ñ¬O¡G%s" ANSI_RESET, - cuser.userid, x.userid, changefrom, x.money, - cuser.userid, reason); - snprintf(title, sizeof(title), - "[¤½¦w³ø§i] ¯¸ªø%sקï%s¿ú³ø§i", cuser.userid, - x.userid); - post_msg(GLOBAL_SECURITY, title, msg, "[¨t²Î¦w¥þ§½]"); - setumoney(unum, x.money); - } - passwd_update(unum, &x); - if(perm_changed) - sendalert(x.userid, ALERT_PWD_PERM); // force to reload perm - - // resolve_over18 only works for cuser - if (!adminmode) - resolve_over18(); - } -} - -int -u_info(void) -{ - move(2, 0); - user_display(&cuser, 0); - uinfo_query(&cuser, 0, usernum); - strlcpy(currutmp->nickname, cuser.nickname, sizeof(currutmp->nickname)); - return 0; -} - -int -u_cloak(void) -{ - outs((currutmp->invisible ^= 1) ? MSG_CLOAKED : MSG_UNCLOAK); - return XEASY; -} - -void -showplans_userec(userec_t *user) -{ - char genbuf[200]; - - if(user->userlevel & PERM_VIOLATELAW) - { - outs(" " ANSI_COLOR(1;31) "¦¹¤H¹H³W ©|¥¼Ãº¥æ»@³æ" ANSI_RESET); - return; - } - -#ifdef CHESSCOUNTRY - if (user_query_mode) { - int i = 0; - FILE *fp; - - sethomefile(genbuf, user->userid, chess_photo_name[user_query_mode - 1]); - if ((fp = fopen(genbuf, "r")) != NULL) - { - char photo[6][256]; - int kingdom_bid = 0; - int win = 0, lost = 0; - - move(7, 0); - while (i < 12 && fgets(genbuf, 256, fp)) - { - chomp(genbuf); - if (i < 6) /* Ū·Ó¤ùÀÉ */ - strcpy(photo[i], genbuf); - else if (i == 6) - kingdom_bid = atoi(genbuf); - else - prints("%s %s\n", photo[i - 7], genbuf); - - i++; - } - fclose(fp); - - if (user_query_mode == 1) { - win = user->five_win; - lost = user->five_lose; - } else if(user_query_mode == 2) { - win = user->chc_win; - lost = user->chc_lose; - } - prints("%s <Á`¦@¾ÔÁZ> %d ³Ó %d ±Ñ\n", photo[5], win, lost); - - - /* ´Ñ°ê°êÀ² */ - setapath(genbuf, bcache[kingdom_bid - 1].brdname); - strlcat(genbuf, "/chess_ensign", sizeof(genbuf)); - show_file(genbuf, 13, 10, SHOWFILE_ALLOW_COLOR); - return; - } - } -#endif /* defined(CHESSCOUNTRY) */ - - sethomefile(genbuf, user->userid, fn_plans); - if (!show_file(genbuf, 7, MAX_QUERYLINES, SHOWFILE_ALLOW_COLOR)) - prints("¡mÓ¤H¦W¤ù¡n%s ¥Ø«e¨S¦³¦W¤ù", user->userid); -} - -void -showplans(const char *uid) -{ - userec_t user; - if(getuser(uid, &user)) - showplans_userec(&user); -} -/* - * return value: how many items displayed */ -int -showsignature(char *fname, int *j, SigInfo *si) -{ - FILE *fp; - char buf[256]; - int i, lines = scr_lns; - char ch; - - clear(); - move(2, 0); - lines -= 3; - - setuserfile(fname, "sig.0"); - *j = strlen(fname) - 1; - si->total = 0; - si->max = 0; - - for (ch = '1'; ch <= '9'; ch++) { - fname[*j] = ch; - if ((fp = fopen(fname, "r"))) { - si->total ++; - si->max = ch - '1'; - if(lines > 0 && si->max >= si->show_start) - { - prints(ANSI_COLOR(36) "¡i ñ¦WÀÉ.%c ¡j" ANSI_RESET "\n", ch); - lines--; - if(lines > MAX_SIGLINES/2) - si->show_max = si->max; - for (i = 0; lines > 0 && i < MAX_SIGLINES && - fgets(buf, sizeof(buf), fp) != NULL; i++) - outs(buf), lines--; - } - fclose(fp); - } - } - if(lines > 0) - si->show_max = si->max; - return si->max; -} - -int -u_editsig(void) -{ - int aborted; - char ans[4]; - int j, browsing = 0; - char genbuf[MAXPATHLEN]; - SigInfo si; - - memset(&si, 0, sizeof(si)); - -browse_sigs: - - showsignature(genbuf, &j, &si); - getdata(0, 0, (browsing || (si.max > si.show_max)) ? - "ñ¦WÀÉ (E)½s¿è (D)§R°£ (N)½¶ (Q)¨ú®ø¡H[Q] ": - "ñ¦WÀÉ (E)½s¿è (D)§R°£ (Q)¨ú®ø¡H[Q] ", - ans, sizeof(ans), LCECHO); - - if(ans[0] == 'n') - { - si.show_start = si.show_max + 1; - if(si.show_start > si.max) - si.show_start = 0; - browsing = 1; - goto browse_sigs; - } - - aborted = 0; - if (ans[0] == 'd') - aborted = 1; - else if (ans[0] == 'e') - aborted = 2; - - if (aborted) { - if (!getdata(1, 0, "½Ð¿ï¾Üñ¦WÀÉ(1-9)¡H[1] ", ans, sizeof(ans), DOECHO)) - ans[0] = '1'; - if (ans[0] >= '1' && ans[0] <= '9') { - genbuf[j] = ans[0]; - if (aborted == 1) { - unlink(genbuf); - outs(msg_del_ok); - } else { - setutmpmode(EDITSIG); - aborted = vedit(genbuf, NA, NULL); - if (aborted != -1) - outs("ñ¦WÀɧó·s§¹²¦"); - } - } - pressanykey(); - } - return 0; -} - -int -u_editplan(void) -{ - char genbuf[200]; - - getdata(b_lines - 1, 0, "¦W¤ù (D)§R°£ (E)½s¿è [Q]¨ú®ø¡H[Q] ", - genbuf, 3, LCECHO); - - if (genbuf[0] == 'e') { - int aborted; - - setutmpmode(EDITPLAN); - setuserfile(genbuf, fn_plans); - aborted = vedit(genbuf, NA, NULL); - if (aborted != -1) - outs("¦W¤ù§ó·s§¹²¦"); - pressanykey(); - return 0; - } else if (genbuf[0] == 'd') { - setuserfile(genbuf, fn_plans); - unlink(genbuf); - outmsg("¦W¤ù§R°£§¹²¦"); - } - return 0; -} - -int -isvalidemail(const char *email) -{ - FILE *fp; - char buf[128], *c; - if (!strstr(email, "@")) - return 0; - for (c = strstr(email, "@"); *c != 0; ++c) - if ('A' <= *c && *c <= 'Z') - *c += 32; - - if ((fp = fopen("etc/banemail", "r"))) { - while (fgets(buf, sizeof(buf), fp)) { - if (buf[0] == '#') - continue; - chomp(buf); - if (buf[0] == 'A' && strcasecmp(&buf[1], email) == 0) - return 0; - if (buf[0] == 'P' && strcasestr(email, &buf[1])) - return 0; - if (buf[0] == 'S' && strcasecmp(strstr(email, "@") + 1, &buf[1]) == 0) - return 0; - } - fclose(fp); - } - return 1; -} - -/* ¦C¥X©Ò¦³µù¥U¨Ï¥ÎªÌ */ -struct ListAllUsetCtx { - int usercounter; - int totalusers; - unsigned short u_list_special; - int y; -}; - -static int -u_list_CB(void *data, int num, userec_t * uentp) -{ - char permstr[8], *ptr; - register int level; - struct ListAllUsetCtx *ctx = (struct ListAllUsetCtx*) data; - (void)num; - - if (uentp == NULL) { - move(2, 0); - clrtoeol(); - prints(ANSI_COLOR(7) " ¨Ï¥ÎªÌ¥N¸¹ %-25s ¤W¯¸ ¤å³¹ %s " - "³Ìªñ¥úÁ{¤é´Á " ANSI_COLOR(0) "\n", - "ºï¸¹¼ÊºÙ", - HasUserPerm(PERM_SEEULEVELS) ? "µ¥¯Å" : ""); - ctx->y = 3; - return 0; - } - if (bad_user_id(uentp->userid)) - return 0; - - if ((uentp->userlevel & ~(ctx->u_list_special)) == 0) - return 0; - - if (ctx->y == b_lines) { - int ch; - prints(ANSI_COLOR(34;46) " ¤wÅã¥Ü %d/%d ¤H(%d%%) " ANSI_COLOR(31;47) " " - "(Space)" ANSI_COLOR(30) " ¬Ý¤U¤@¶ " ANSI_COLOR(31) "(Q)" ANSI_COLOR(30) " Â÷¶} " ANSI_RESET, - ctx->usercounter, ctx->totalusers, ctx->usercounter * 100 / ctx->totalusers); - ch = igetch(); - if (ch == 'q' || ch == 'Q') - return -1; - ctx->y = 3; - } - if (ctx->y == 3) { - move(3, 0); - clrtobot(); - } - level = uentp->userlevel; - strlcpy(permstr, "----", 8); - if (level & PERM_SYSOP) - permstr[0] = 'S'; - else if (level & PERM_ACCOUNTS) - permstr[0] = 'A'; - else if (level & PERM_SYSOPHIDE) - permstr[0] = 'p'; - - if (level & (PERM_BOARD)) - permstr[1] = 'B'; - else if (level & (PERM_BM)) - permstr[1] = 'b'; - - if (level & (PERM_XEMPT)) - permstr[2] = 'X'; - else if (level & (PERM_LOGINOK)) - permstr[2] = 'R'; - - if (level & (PERM_CLOAK | PERM_SEECLOAK)) - permstr[3] = 'C'; - - ptr = (char *)Cdate(&uentp->lastlogin); - ptr[18] = '\0'; - prints("%-14s %-27.27s%5d %5d %s %s\n", - uentp->userid, - uentp->nickname, - uentp->numlogins, uentp->numposts, - HasUserPerm(PERM_SEEULEVELS) ? permstr : "", ptr); - ctx->usercounter++; - ctx->y++; - return 0; -} - -int -u_list(void) -{ - char genbuf[3]; - struct ListAllUsetCtx data, *ctx = &data; - - setutmpmode(LAUSERS); - ctx->u_list_special = ctx->usercounter = 0; - ctx->totalusers = SHM->number; - if (HasUserPerm(PERM_SEEULEVELS)) { - getdata(b_lines - 1, 0, "Æ[¬Ý [1]¯S®íµ¥¯Å (2)¥þ³¡¡H", - genbuf, 3, DOECHO); - if (genbuf[0] != '2') - ctx->u_list_special = PERM_BASIC | PERM_CHAT | PERM_PAGE | PERM_POST | PERM_LOGINOK | PERM_BM; - } - u_list_CB(ctx, 0, NULL); - passwd_apply(ctx, u_list_CB); - move(b_lines, 0); - clrtoeol(); - prints(ANSI_COLOR(34;46) " ¤wÅã¥Ü %d/%d ªº¨Ï¥ÎªÌ(¨t²Î®e¶qµL¤W) " - ANSI_COLOR(31;47) " (½Ð«ö¥ô·NÁäÄ~Äò) " ANSI_RESET, ctx->usercounter, ctx->totalusers); - igetch(); - return 0; -} - -#ifdef DBCSAWARE - -/* detect if user is using an evil client that sends double - * keys for DBCS data. - * True if client is evil. - */ - -int u_detectDBCSAwareEvilClient() -{ - int ret = 0; - - clear(); - stand_title("³]©w¦Û°Ê°»´úÂù¦ì¤¸¦r¶° (¥þ«¬¤¤¤å)"); - move(2, 0); - outs(ANSI_RESET - "* ¥»¯¸¤ä´©¦Û°Ê°»´ú¤¤¤å¦rªº²¾°Ê»P½s¿è¡A¦ý¦³¨Ç³s½uµ{¦¡ (¦pxxMan)\n" - " ¤]·|¦Û¦æ¸Õ¹Ï°»´ú¡B¦h°e«öÁä¡A©ó¬O«K·|³y¦¨" ANSI_COLOR(1;37) - "¤@¦¸²¾°Ê¨âÓ¤¤¤å¦rªº²{¶H¡C" ANSI_RESET "\n\n" - "* Åý³s½uµ{¦¡³B²z²¾°Ê®e©ö³y¦¨Åã¥Ü¤Î²¾°Ê¤W»~§Pªº°ÝÃD¡A©Ò¥H§ÚÌ«Øij±z\n" - " Ãö³¬¸Óµ{¦¡¤Wªº³]©w¡]³q±`¥s¡u°»´ú(¥þ«¬©ÎÂù¦ì¤¸²Õ)¤¤¤å¡v¡^¡A\n" - " Åý BBS ¨t²Î¥i¥H¥¿½Tªº±±¨î§Aªºµe±¡C\n\n" - ANSI_COLOR(1;33) - "* ¦pªG±z¬Ý¤£À´¤W±ªº»¡©ú¤]µL©Ò¿×¡A§ÚÌ·|¦Û°Ê°»´ú¾A¦X±zªº³]©w¡C" - ANSI_RESET "\n" - " ½Ð¦b³]©w¦n³s½uµ{¦¡¦¨±z°¾¦nªº¼Ò¦¡«á«ö" ANSI_COLOR(1;33) - "¤@¤U" ANSI_RESET "±zÁä½L¤Wªº" ANSI_COLOR(1;33) - "¡ö" ANSI_RESET "\n" ANSI_COLOR(1;36) - " (¥ª¥k¤è¦VÁä©Î¼g BS/Backspace ªºË°hÁä»P Del §R°£Á䧡¥i)\n" - ANSI_RESET); - - /* clear buffer */ - peek_input(0.1, Ctrl('C')); - drop_input(); - - while (1) - { - int ch = 0; - - move(14, 0); - outs("³o¬O°»´ú°Ï¡A±zªº´å¼Ð·|¥X²{¦b" - ANSI_COLOR(7) "³o¸Ì" ANSI_RESET); - move(14, 15*2); - ch = igetch(); - if(ch != KEY_LEFT && ch != KEY_RIGHT && - ch != Ctrl('H') && ch != '\177') - { - move(16, 0); - bell(); - outs("½Ð«ö¤@¤U¤W±«ü©wªºÁä¡I §A«ö¨ì§OªºÁä¤F¡I"); - } else { - move(16, 0); - /* Actually you may also use num_in_buf here. those clients - * usually sends doubled keys together in one packet. - * However when I was writing this, a bug (existed for more than 3 - * years) of num_in_buf forced me to write new wait_input. - * Anyway it is fixed now. - */ - refresh(); - if(wait_input(0.1, 0)) - // if(igetch() == ch) - // if (num_in_buf() > 0) - { - /* evil dbcs aware client */ - outs("°»´ú¨ì±zªº³s½uµ{¦¡·|¦Û¦æ³B²z´å¼Ð²¾°Ê¡C\n" - // "Y¤é«á¦]¦¹³y¦¨ÂsÄý¤Wªº°ÝÃD¥»¯¸®¤¤£³B²z¡C\n\n" - "¤w³]©w¬°¡uÅý±zªº³s½uµ{¦¡³B²z´å¼Ð²¾°Ê¡v\n"); - ret = 1; - } else { - /* good non-dbcs aware client */ - outs("±zªº³s½uµ{¦¡¦ü¥G¤£·|¦h°e«öÁä¡A" - "³o¼Ë BBS ¥i¥H§óºë·Çªº±±¨îµe±¡C\n" - "¤w³]©w¬°¡uÅý BBS ¦øªA¾¹ª½±µ³B²z´å¼Ð²¾°Ê¡v\n"); - ret = 0; - } - outs( "\nY·Q§ïÅܳ]©w½Ð¦Ü Ó¤H³]©w°Ï ¡÷ Ó¤H¤Æ³]©w ¡÷ \n" - " ½Õ¾ã¡u¦Û°Ê°»´úÂù¦ì¤¸¦r¶°(¦p¥þ«¬¤¤¤å)¡v¤§³]©w"); - while(num_in_buf()) - igetch(); - break; - } - } - drop_input(); - pressanykey(); - return ret; -} -#endif - -/* vim:sw=4 - */ diff --git a/mbbsd/var.c b/mbbsd/var.c deleted file mode 100644 index ca50824c..00000000 --- a/mbbsd/var.c +++ /dev/null @@ -1,628 +0,0 @@ -/* $Id$ */ -#define INCLUDE_VAR_H -#include "bbs.h" - -const char * const str_permid[] = { - "°ò¥»Åv¤O", /* PERM_BASIC */ - "¶i¤J²á¤Ñ«Ç", /* PERM_CHAT */ - "§ä¤H²á¤Ñ", /* PERM_PAGE */ - "µoªí¤å³¹", /* PERM_POST */ - "µù¥Uµ{§Ç»{ÃÒ", /* PERM_LOGINOK */ - "«H¥óµL¤W", /* PERM_MAILLIMIT */ - "Áô¨³N", /* PERM_CLOAK */ - "¬Ý¨£§ÔªÌ", /* PERM_SEECLOAK */ - "¥Ã¤[«O¯d±b¸¹", /* PERM_XEMPT */ - "¯¸ªøÁô¨³N", /* PERM_DENYPOST */ - "ªO¥D", /* PERM_BM */ - "±b¸¹Á`ºÞ", /* PERM_ACCOUNTS */ - "²á¤Ñ«ÇÁ`ºÞ", /* PERM_CHATCLOAK */ - "¬ÝªOÁ`ºÞ", /* PERM_BOARD */ - "¯¸ªø", /* PERM_SYSOP */ - "BBSADM", /* PERM_POSTMARK */ - "¤£¦C¤J±Æ¦æº]", /* PERM_NOTOP */ - "¹Hªk³q½r¤¤", /* PERM_VIOLATELAW */ -#ifdef PLAY_ANGEL - "¥i¾á¥ô¤p¤Ñ¨Ï", /* PERM_ANGEL */ -#else - "¥¼¨Ï¥Î", -#endif - "¤£¤¹³\\»{ÃÒ½Xµù¥U", /* PERM_NOREGCODE */ - "µøı¯¸ªø", /* PERM_VIEWSYSOP */ - "Æ[¹î¨Ï¥ÎªÌ¦æÂÜ", /* PERM_LOGUSER */ - "æ͹ܤ½Åv", /* PERM_NOCITIZEN */ - "¸s²Õªø", /* PERM_SYSSUPERSUBOP */ - "±b¸¹¼f®Ö²Õ", /* PERM_ACCTREG */ - "µ{¦¡²Õ", /* PERM_PRG */ - "¬¡°Ê²Õ", /* PERM_ACTION */ - "¬ü¤u²Õ", /* PERM_PAINT */ - "ĵ¹îÁ`ºÞ", /* PERM_POLICE_MAN */ - "¤p²Õªø", /* PERM_SYSSUBOP */ - "°h¥ð¯¸ªø", /* PERM_OLDSYSOP */ - "ĵ¹î" /* PERM_POLICE */ -}; - -const char * const str_permboard[] = { - "¤£¥i Zap", /* BRD_NOZAP */ - "¤£¦C¤J²Îp", /* BRD_NOCOUNT */ - "¤£Âà«H", /* BRD_NOTRAN */ - "¸s²ÕªO", /* BRD_GROUPBOARD */ - "ÁôÂêO", /* BRD_HIDE */ - "¨î(¤£»Ý³]©w)", /* BRD_POSTMASK */ - "°Î¦WªO", /* BRD_ANONYMOUS */ - "¹w³]°Î¦WªO", /* BRD_DEFAULTANONYMOUS */ - "¹Hªk§ï¶i¤¤¬ÝªO", /* BRD_BAD */ - "³s¸p±M¥Î¬ÝªO", /* BRD_VOTEBOARD */ - "¤wĵ§in¼o°£", /* BRD_WARNEL */ - "¼öªù¬ÝªO¸s²Õ", /* BRD_TOP */ - "¤£¥i±ÀÂË", /* BRD_NORECOMMEND */ - "¥¬¸¨®æ", /* BRD_BLOG */ - "ªO¥D³]©w¦C¤J°O¿ý", /* BRD_BMCOUNT */ - "³sµ²¬ÝªO", /* BRD_SYMBOLIC */ - "¤£¥i¼N", /* BRD_NOBOO */ - "¹w³] Local Save", /* BRD_LOCALSAVE */ - "ªO¤Íµo¤å", /* BRD_RESTRICTEDPOST */ - "Guest¥i¥Hµoªí", /* BRD_GUESTPOST */ -#ifdef USE_COOLDOWN - "§NÀR", /* BRD_COOLDOWN */ -#else - "§NÀR(¥»¯¸µL®Ä)", /* BRD_COOLDOWN */ -#endif -#ifdef USE_AUTOCPLOG - "¦Û°Ê¯dÂà¿ý°O¿ý", /* BRD_CPLOG */ -#else - "Âà¿ý°O¿ý(¥»¯¸µL®Ä)", /* BRD_CPLOG */ -#endif - "¸T¤î§Ö³t±À¤å", /* BRD_NOFASTRECMD */ - "±À¤å°O¿ý IP", /* BRD_IPLOGRECMD */ - "¤Q¤K¸T", /* BRD_OVER18 */ - "¨S·Q¨ì", - "¨S·Q¨ì", - "¨S·Q¨ì", - "¨S·Q¨ì", - "¨S·Q¨ì", - "¨S·Q¨ì", - "¨S·Q¨ì", -}; - -int usernum; -int currmode = 0; -int currsrmode = 0; -int curredit = 0; -int paste_level; -int currbid; -char quote_file[80] = "\0"; -char quote_user[80] = "\0"; -char currtitle[TTLEN + 1] = "\0"; -char currauthor[IDLEN + 2] = "\0"; -const char *currboard = "\0"; -char currBM[IDLEN * 3 + 10]; -const char reset_color[4] = ANSI_RESET; -char margs[64] = "\0"; /* main argv list */ -pid_t currpid; /* current process ID */ -time4_t login_start_time; -time4_t start_time; -userec_t cuser; /* current user structure */ -crosspost_t postrecord; /* anti cross post */ -unsigned int currbrdattr; -unsigned int currstat; -unsigned char currfmode; /* current file mode */ - -/* global string variables */ -/* filename */ - -char * const fn_passwd = FN_PASSWD; -char * const fn_board = FN_BOARD; -char * const fn_register = "register.new"; -char * const fn_note_ans = FN_NOTE_ANS; -const char * const fn_plans = "plans"; -const char * const fn_writelog = "writelog"; -const char * const fn_talklog = "talklog"; -const char * const fn_overrides = FN_OVERRIDES; -const char * const fn_reject = FN_REJECT; -const char * const fn_canvote = FN_CANVOTE; -const char * const fn_notes = "notes"; -const char * const fn_water = FN_WATER; -const char * const fn_visable = FN_VISABLE; -const char * const fn_mandex = "/.Names"; -const char * const fn_boardlisthelp = FN_BRDLISTHELP; -const char * const fn_boardhelp = FN_BOARDHELP; - -/* are descript in userec.loginview */ - -char * const loginview_file[NUMVIEWFILE][2] = { - {FN_NOTE_ANS, "»Ä²¢W»¶¬y¨¥ªO"}, - {FN_TOPSONG, "ÂIºq±Æ¦æº]"}, - {"etc/topusr", "¤Q¤j±Æ¦æº]"}, - {"etc/topusr100", "¦Ê¤j±Æ¦æº]"}, - {"etc/weather.tmp", "¤Ñ®ð§Ö³ø"}, - {"etc/stock.tmp", "ªÑ¥«§Ö³ø"}, - {"etc/day", "¤µ¤é¤Q¤j¸ÜÃD"}, - {"etc/week", "¤@¶g¤¤Q¤j¸ÜÃD"}, - {"etc/today", "¤µ¤Ñ¤W¯¸¤H¦¸"}, - {"etc/yesterday", "¬Q¤é¤W¯¸¤H¦¸"}, - {"etc/history", "¾ú¥v¤Wªº¤µ¤Ñ"}, - {"etc/topboardman", "ºëµØ°Ï±Æ¦æº]"}, - {"etc/topboard.tmp", "¬ÝªO¤H®ð±Æ¦æº]"}, - {NULL, NULL} -}; - -/* message */ -char * const msg_seperator = MSG_SEPERATOR; - -char * const msg_cancel = MSG_CANCEL; -char * const msg_usr_left = MSG_USR_LEFT; -char * const msg_nobody = MSG_NOBODY; - -char * const msg_sure_ny = MSG_SURE_NY; -char * const msg_sure_yn = MSG_SURE_YN; - -char * const msg_bid = MSG_BID; -char * const msg_uid = MSG_UID; - -char * const msg_del_ok = MSG_DEL_OK; -char * const msg_del_ny = MSG_DEL_NY; - -char * const msg_fwd_ok = MSG_FWD_OK; -char * const msg_fwd_err1 = MSG_FWD_ERR1; -char * const msg_fwd_err2 = MSG_FWD_ERR2; - -char * const err_board_update = ERR_BOARD_UPDATE; -char * const err_bid = ERR_BID; -char * const err_uid = ERR_UID; -char * const err_filename = ERR_FILENAME; - -char * const str_mail_address = "." BBSUSER "@" MYHOSTNAME; -char * const str_new = "new"; -char * const str_reply = "Re: "; -char * const str_space = " \t\n\r"; -char * const str_sysop = "SYSOP"; -char * const str_author1 = STR_AUTHOR1; -char * const str_author2 = STR_AUTHOR2; -char * const str_post1 = STR_POST1; -char * const str_post2 = STR_POST2; -char * const BBSName = BBSNAME; - -/* MAX_MODES is defined in common.h */ - -char * const ModeTypeTable[] = { - "µo§b", /* IDLE */ - "¥D¿ï³æ", /* MMENU */ - "¨t²ÎºûÅ@", /* ADMIN */ - "¶l¥ó¿ï³æ", /* MAIL */ - "¥æ½Í¿ï³æ", /* TMENU */ - "¨Ï¥ÎªÌ¿ï³æ", /* UMENU */ - "XYZ ¿ï³æ", /* XMENU */ - "¤ÀÃþ¬ÝªO", /* CLASS */ - "Play¿ï³æ", /* PMENU */ - "½s¯S§O¦W³æ", /* NMENU */ - BBSMNAME2 "¶q³c©±", /* PSALE */ - "µoªí¤å³¹", /* POSTING */ - "¬ÝªO¦Cªí", /* READBRD */ - "¾\\Ū¤å³¹", /* READING */ - "·s¤å³¹¦Cªí", /* READNEW */ - "¿ï¾Ü¬ÝªO", /* SELECT */ - "Ū«H", /* RMAIL */ - "¼g«H", /* SMAIL */ - "²á¤Ñ«Ç", /* CHATING */ - "¨ä¥L", /* XMODE */ - "´M§ä¦n¤Í", /* FRIEND */ - "¤W½u¨Ï¥ÎªÌ", /* LAUSERS */ - "¨Ï¥ÎªÌ¦W³æ", /* LUSERS */ - "°lÂܯ¸¤Í", /* MONITOR */ - "©I¥s", /* PAGE */ - "¬d¸ß", /* TQUERY */ - "¥æ½Í", /* TALK */ - "½s¦W¤ùÀÉ", /* EDITPLAN */ - "½sñ¦WÀÉ", /* EDITSIG */ - "§ë²¼¤¤", /* VOTING */ - "³]©w¸ê®Æ", /* XINFO */ - "±Hµ¹¯¸ªø", /* MSYSOP */ - "¨L¨L¨L", /* WWW */ - "¥´¤j¦Ñ¤G", /* BIG2 */ - "¦^À³", /* REPLY */ - "³Q¤ô²y¥´¤¤", /* HIT */ - "¤ô²y·Ç³Æ¤¤", /* DBACK */ - "µ§°O¥»", /* NOTE */ - "½s¿è¤å³¹", /* EDITING */ - "µo¨t²Î³q§i", /* MAILALL */ - "ºN¨â°é", /* MJ */ - "¹q¸£¾Ü¤Í", /* P_FRIEND */ - "¤W¯¸³~¤¤", /* LOGIN */ - "¬d¦r¨å", /* DICT */ - "¥´¾ôµP", /* BRIDGE */ - "§äÀÉ®×", /* ARCHIE */ - "¥´¦a¹«", /* GOPHER */ - "¬ÝNews", /* NEWS */ - "±¡®Ñ²£¥Í¾¹", /* LOVE */ - "½s¿è»²§U¾¹", /* EDITEXP */ - "¥Ó½ÐIP¦ì§}", /* IPREG */ - "ºôºÞ¿ì¤½¤¤", /* NetAdm */ - "µêÀÀ¹ê·~§{", /* DRINK */ - "pºâ¾÷", /* CAL */ - "½s¿è®y¥k»Ê", /* PROVERB */ - "¤½§GÄæ", /* ANNOUNCE */ - "¨è¬y¨¥ªO", /* EDNOTE */ - "^º~½Ķ¾÷", /* CDICT */ - "À˵ø¦Û¤vª««~", /* LOBJ */ - "ÂIºq", /* OSONG */ - "¥¿¦bª±¤pÂû", /* CHICKEN */ - "ª±±m¨é", /* TICKET */ - "²q¼Æ¦r", /* GUESSNUM */ - "¹C¼Ö³õ", /* AMUSE */ - "³æ¤H¶Â¥Õ´Ñ", /* OTHELLO */ - "ª±»ë¤l", /* DICE */ - "µo²¼¹ï¼ú", /* VICE */ - "¹G¹Gáàing", /* BBCALL */ - "ú»@³æ", /* CROSSPOST */ - "¤¤l´Ñ", /* M_FIVE */ - "21ÂIing", /* JACK_CARD */ - "10ÂI¥bing", /* TENHALF */ - "¶W¯Å¤E¤Q¤E", /* CARD_99 */ - "¤õ¨®¬d¸ß", /* RAIL_WAY */ - "·j´M¿ï³æ", /* SREG */ - "¤U¶H´Ñ", /* CHC */ - "¤U·t´Ñ", /* DARK */ - "NBA¤j²q´ú", /* TMPJACK */ - BBSMNAME2 "¬dº]¨t²Î", /* JCEE */ - "«½s¤å³¹", /* REEDIT */ - "³¡¸¨®æ", /* BLOGGING */ - "¬Ý´Ñ", /* CHESSWATCHING */ - "¤U³ò´Ñ", /* UMODE_GO */ - "[¨t²Î¿ù»~]", /* DEBUGSLEEPING */ - "³s¤»´Ñ", /* UMODE_CONN6 */ - "¶Â¥Õ´Ñ", /* REVERSI */ - "BBS-Lua", /* UMODE_BBSLUA */ - "¼½©ñ°Êµe", /* UMODE_ASCIIMOVIE */ - "", - "", - "", // 90 - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", // 100 - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", // 110 - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", // 120 - "", - "", - "", - "", - "", - "", - "", - "" -}; - -/* term.c */ -int b_lines = 23; // bottom line of screen -int t_lines = 24; // term lines -int p_lines = 20; -int t_columns = 80; - -/* refer to ansi.h for *len */ -char * const strtstandout = ANSI_COLOR(7); -const int strtstandoutlen = 4; -char * const endstandout = ANSI_RESET; -const int endstandoutlen = 3; -char * const clearbuf = ESC_STR "[H" ESC_STR "[J"; -const int clearbuflen = 6; -char * const cleolbuf = ESC_STR "[K"; -const int cleolbuflen = 3; -char * const scrollrev = ESC_STR "M"; -const int scrollrevlen = 2; -int automargins = 1; - -/* io.c */ -time4_t now; -int KEY_ESC_arg; -int watermode = -1; -int wmofo = NOTREPLYING; -/* - * WATERMODE(WATER_ORIG) | WATERMODE(WATER_NEW): - * ???????????????????? - * Ptt ¤ô²y¦^ÅU (FIXME: guessed by scw) - * watermode = -1 ¨S¦b¦^¤ô²y - * = 0 ¦b¦^¤W¤@Áû¤ô²y (Ctrl-R) - * > 0 ¦b¦^«e n Áû¤ô²y (Ctrl-R Ctrl-R) - * - * WATERMODE(WATER_OFO) by in2 - * wmofo = NOTREPLYING ¨S¦b¦^¤ô²y - * = REPLYING ¥¿¦b¦^¤ô²y - * = RECVINREPLYING ¦^¤ô²y¶¡¤S±µ¨ì¤ô²y - * - * wmofo >=0 ®É¦¬¨ì¤ô²y±N¥uÅã¥Ü, ¤£·|¨ìwater[]¸Ì, - * «Ý¦^§¹¤ô²yªº®ÉÔ¤@¦¸¼g¤J. - */ - - -/* cache.c */ -int numboards = -1; -SHM_t *SHM; -boardheader_t *bcache; -userinfo_t *currutmp; - -/* read.c */ -int TagNum = 0; /* tag's number */ -int TagBoard = -1; /* TagBoard = 0 : user's mailbox */ - /* TagBoard > 0 : bid where last taged */ -char currdirect[64]; - -/* edit.c */ -char save_title[STRLEN]; - -/* bbs.c */ -time4_t board_visit_time = 0; -char real_name[IDLEN + 1]; -char local_article; - -/* mbbsd.c */ -char raw_connection = 0; -char fromhost[STRLEN] = "\0"; -char water_usies = 0; -FILE *fp_writelog = NULL; -water_t *water, *swater[6], *water_which; -char over18 = 0; - -/* chc_play.c */ - -/* user.c */ -#ifdef CHESSCOUNTRY -int user_query_mode; -/* - * user_query_mode = 0 simple data - * = 1 gomoku chess country data - * = 2 chc chess country data - * = 3 go chess country data - */ -#endif /* defined(CHESSCOUNTRY) */ - -/* screen.c */ -#define scr_lns t_lines -#define scr_cols ANSILINELEN -screenline_t *big_picture = NULL; -char roll = 0; -char msg_occupied = 0; - -/* gomo.c */ -const char * const bw_chess[] = {"¡³", "¡´", "¡C", "¡E"}; -const unsigned char * const pat_gomoku /* [1954] */ =(unsigned char*) - /* 0 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 16 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x55\xcc\x00\x00\x00\x00" - /* 32 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x33\x00\x44\x00\x33\x00\x00\x00" - /* 48 */ "\x00\x22\x00\x55\x00\x22\x00\x00\x00\x44\x33\x66\x55\xcc\x33\x66" - /* 64 */ "\x55\xcc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00" - /* 80 */ "\x55\x00\x55\x00\x05\x00\x55\x02\x46\x00\xaa\x00\x00\x55\x00\x55" - /* 96 */ "\x00\x05\x00\x55\x00\x05\x00\x55\x00\x00\x44\xcc\x44\xcc\x05\xbb" - /* 112 */ "\x44\xcc\x05\xbb\x44\xcc\x05\xbb\x00\x00\x00\x00\x00\x00\x00\x00" - /* 128 */ "\x00\x00\x33\x00\x00\x00\x44\x00\x00\x00\x00\x00\x33\x00\x44\x00" - /* 144 */ "\x33\x22\x66\x00\x55\x55\xcc\x00\x33\x00\x00\x00\x00\x22\x00\x55" - /* 160 */ "\x00\x22\x00\x55\x00\x02\x00\x05\x00\x22\x00\x00\x33\x44\x33\x66" - /* 176 */ "\x55\xcc\x33\x66\x55\xcc\x33\x46\x05\xbb\x33\x66\x55\xcc\x00\x00" - /* 192 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x44\x00\x00\x00" - /* 208 */ "\x33\x00\x00\x22\x55\x22\x55\x02\x05\x22\x55\x02\x46\x22\xaa\x55" - /* 224 */ "\xcc\x22\x55\x02\x46\x22\xaa\x00\x22\x55\x22\x55\x02\x05\x22\x55" - /* 240 */ "\x02\x05\x22\x55\x02\x05\x22\x55\x02\x05\x22\x55\x02\x44\x66\xcc" - /* 256 */ "\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x66\xcc\x46\xbb" - /* 272 */ "\x66\xcc\x46\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x33\x00" - /* 288 */ "\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x00\x00" - /* 304 */ "\x03\x00\x44\x00\x33\x22\x66\x00\x55\x55\xcc\x00\x33\x22\x66\x00" - /* 320 */ "\x55\x55\xcc\x00\x03\x00\x00\x00\x00\x02\x00\x55\x00\x02\x00\x55" - /* 336 */ "\x00\x02\x00\x05\x00\x02\x00\x55\x00\x02\x02\x46\x00\x02\x00\x55" - /* 352 */ "\x55\x05\x55\x46\xaa\xcc\x55\x46\xaa\xcc\x55\x06\x5a\xbb\x55\x46" - /* 368 */ "\xaa\xcc\x55\x06\x5a\xbb\x55\x46\xaa\xcc\x00\x00\x00\x00\x00\x00" - /* 384 */ "\x00\x00\x00\x00\x03\x00\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22" - /* 400 */ "\x66\x00\x00\x00\x55\x00\x55\x55\x05\x55\x05\x55\x05\x55\x05\x55" - /* 416 */ "\x46\x55\x5a\xaa\xcc\x55\x05\x55\x46\x55\x5a\xaa\xcc\x55\x05\x55" - /* 432 */ "\x06\x55\x0a\x55\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05" - /* 448 */ "\x55\x05\x55\x05\x55\x05\x55\x05\x55\x46\x55\x05\x55\x5a\x55\x5a" - /* 464 */ "\xaa\xcc\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb" - /* 480 */ "\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb" - /* 496 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x33\x00\x00\x00\x44\x00" - /* 512 */ "\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00" - /* 528 */ "\x00\x00\x00\x00\x33\x00\x44\x00\x33\x22\x66\x00\x55\x55\xcc\x00" - /* 544 */ "\x33\x22\x66\x00\x55\x55\xcc\x00\x33\x02\x46\x00\x05\x05\xbb\x00" - /* 560 */ "\x33\x00\x00\x00\x00\x22\x00\x55\x00\x22\x00\x55\x00\x02\x00\x05" - /* 576 */ "\x00\x22\x00\x55\x00\x02\x02\x46\x00\x22\x00\xaa\x00\x55\x55\xcc" - /* 592 */ "\x00\x22\x00\x00\x33\x44\x33\x66\x55\xcc\x33\x66\x55\xcc\x33\x46" - /* 608 */ "\x05\xbb\x33\x66\x55\xcc\x33\x46\x05\xbb\x33\x66\x55\xcc\x33\x46" - /* 624 */ "\x05\xbb\x33\x66\x55\xcc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 640 */ "\x03\x00\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00" - /* 656 */ "\x55\x00\x55\x55\xcc\x00\x00\x00\x33\x00\x00\x22\x55\x22\x55\x02" - /* 672 */ "\x05\x22\x55\x02\x46\x22\xaa\x55\xcc\x22\x55\x02\x46\x22\xaa\x55" - /* 688 */ "\xcc\x22\x55\x02\x06\x22\x5a\x05\xbb\x22\x55\x02\x46\x22\xaa\x00" - /* 704 */ "\x22\x55\x22\x55\x02\x05\x22\x55\x02\x05\x22\x55\x02\x05\x22\x55" - /* 720 */ "\x02\x05\x22\x55\x02\x46\x22\x55\x02\x5a\x22\xaa\x55\xcc\x22\x55" - /* 736 */ "\x02\x05\x22\x55\x02\x44\x66\xcc\x66\xcc\x46\xbb\x66\xcc\x46\xbb" - /* 752 */ "\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x66\xcc\x46\xbb" - /* 768 */ "\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x66\xcc\x46\xbb\x00\x00\x00\x00" - /* 784 */ "\x00\x00\x00\x00\x00\x00\x33\x00\x00\x00\x44\x00\x00\x00\x33\x00" - /* 800 */ "\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00\x33\x00" - /* 816 */ "\x22\x22\x66\x00\x00\x00\x00\x00\x03\x00\x44\x00\x33\x22\x66\x00" - /* 832 */ "\x55\x55\xcc\x00\x33\x22\x66\x00\x55\x55\xcc\x00\x03\x02\x46\x00" - /* 848 */ "\x05\x05\xbb\x00\x33\x22\x66\x00\x55\x55\xcc\x00\x03\x00\x00\x00" - /* 864 */ "\x00\x02\x00\x55\x00\x02\x00\x55\x00\x02\x00\x05\x00\x02\x00\x55" - /* 880 */ "\x00\x02\x02\x46\x00\x02\x00\xaa\x00\x55\x55\xcc\x00\x02\x00\x55" - /* 896 */ "\x00\x02\x02\x46\x00\x02\x00\x55\x55\x05\x55\x46\xaa\xcc\x55\x46" - /* 912 */ "\xaa\xcc\x55\x06\x5a\xbb\x55\x46\xaa\xcc\x55\x06\x5a\xbb\x55\x46" - /* 928 */ "\xaa\xcc\x55\x06\x5a\xbb\x55\x46\xaa\xcc\x55\x06\x5a\xbb\x55\x46" - /* 944 */ "\xaa\xcc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00" - /* 960 */ "\x44\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55" - /* 976 */ "\xcc\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55" - /* 992 */ "\x05\x55\x05\x55\x05\x55\x05\x55\x46\x55\x5a\xaa\xcc\x55\x05\x55" - /* 1008 */ "\x46\x55\x5a\xaa\xcc\x55\x05\x55\x06\x55\x0a\x5a\xbb\x55\x05\x55" - /* 1024 */ "\x46\x55\x5a\xaa\xcc\x55\x05\x55\x06\x55\x0a\x55\x55\x05\x55\x05" - /* 1040 */ "\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05\x55\x05" - /* 1056 */ "\x55\x46\x55\x05\x55\x5a\x55\x5a\xaa\xcc\x55\x05\x55\x05\x55\x05" - /* 1072 */ "\x55\x46\x55\x05\x55\x5a\x55\x5a\xaa\xcc\xcc\xbb\xcc\xbb\xcc\xbb" - /* 1088 */ "\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb" - /* 1104 */ "\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb" - /* 1120 */ "\xcc\xbb\xcc\xbb\xcc\xbb\xcc\xbb\x00\x00\x00\x00\x00\x00\x00\x00" - /* 1136 */ "\x00\x00\x33\x00\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22\x66\x00" - /* 1152 */ "\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00\x33\x00\x22\x22\x66\x00" - /* 1168 */ "\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00\x00\x00\x33\x00\x44\x00" - /* 1184 */ "\x33\x22\x66\x00\x55\x55\xcc\x00\x33\x22\x66\x00\x55\x55\xcc\x00" - /* 1200 */ "\x33\x02\x46\x00\x05\x05\xbb\x00\x33\x22\x66\x00\x55\x55\xcc\x00" - /* 1216 */ "\x33\x02\x46\x00\x05\x05\xbb\x00\x33\x00\x00\x00\x00\x22\x00\x55" - /* 1232 */ "\x00\x22\x00\x55\x00\x02\x00\x05\x00\x22\x00\x55\x00\x02\x02\x46" - /* 1248 */ "\x00\x22\x00\xaa\x00\x55\x55\xcc\x00\x22\x00\x55\x00\x02\x02\x46" - /* 1264 */ "\x00\x22\x00\xaa\x00\x55\x55\xcc\x00\x22\x00\x00\x03\x44\x33\x66" - /* 1280 */ "\x55\xcc\x33\x66\x55\xcc\x03\x46\x05\xbb\x33\x66\x55\xcc\x03\x46" - /* 1296 */ "\x05\xbb\x33\x66\x55\xcc\x03\x46\x05\xbb\x33\x66\x55\xcc\x03\x46" - /* 1312 */ "\x05\xbb\x33\x66\x55\xcc\x03\x46\x05\xbb\x33\x66\x55\xcc\x00\x00" - /* 1328 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x44\x00\x00\x00" - /* 1344 */ "\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00" - /* 1360 */ "\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00" - /* 1376 */ "\x03\x00\x00\x02\x55\x02\x55\x02\x05\x02\x55\x02\x46\x02\xaa\x55" - /* 1392 */ "\xcc\x02\x55\x02\x46\x02\xaa\x55\xcc\x02\x55\x02\x06\x02\x5a\x05" - /* 1408 */ "\xbb\x02\x55\x02\x46\x02\xaa\x55\xcc\x02\x55\x02\x06\x02\x5a\x05" - /* 1424 */ "\xbb\x02\x55\x02\x46\x02\xaa\x00\x02\x55\x02\x55\x02\x05\x02\x55" - /* 1440 */ "\x02\x05\x02\x55\x02\x05\x02\x55\x02\x05\x02\x55\x02\x46\x02\x55" - /* 1456 */ "\x02\x5a\x02\xaa\x55\xcc\x02\x55\x02\x05\x02\x55\x02\x46\x02\x55" - /* 1472 */ "\x02\x5a\x02\xaa\x55\xcc\x02\x55\x02\x05\x02\x55\x02\x05\x46\xcc" - /* 1488 */ "\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb" - /* 1504 */ "\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb" - /* 1520 */ "\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb\x46\xcc\x06\xbb" - /* 1536 */ "\x46\xcc\x06\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x33\x00" - /* 1552 */ "\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00" - /* 1568 */ "\x55\x55\xcc\x00\x00\x00\x33\x00\x22\x22\x66\x00\x00\x00\x55\x00" - /* 1584 */ "\x55\x55\xcc\x00\x00\x00\x33\x00\x02\x02\x46\x00\x00\x00\x00\x00" - /* 1600 */ "\x03\x00\x44\x00\x33\x22\x66\x00\x55\x55\xcc\x00\x33\x22\x66\x00" - /* 1616 */ "\x55\x55\xcc\x00\x03\x02\x46\x00\x05\x05\xbb\x00\x33\x22\x66\x00" - /* 1632 */ "\x55\x55\xcc\x00\x03\x02\x46\x00\x05\x05\xbb\x00\x33\x22\x66\x00" - /* 1648 */ "\x55\x55\xcc\x00\x03\x00\x00\x00\x00\x02\x00\x55\x00\x02\x00\x55" - /* 1664 */ "\x00\x02\x00\x05\x00\x02\x00\x55\x00\x02\x02\x46\x00\x02\x00\xaa" - /* 1680 */ "\x00\x55\x55\xcc\x00\x02\x00\x55\x00\x02\x02\x46\x00\x02\x00\xaa" - /* 1696 */ "\x00\x55\x55\xcc\x00\x02\x00\x55\x00\x02\x02\x06\x00\x02\x00\x05" - /* 1712 */ "\x05\x05\x05\x46\x5a\xcc\x05\x46\x5a\xcc\x05\x06\x0a\xbb\x05\x46" - /* 1728 */ "\x5a\xcc\x05\x06\x0a\xbb\x05\x46\x5a\xcc\x05\x06\x0a\xbb\x05\x46" - /* 1744 */ "\x5a\xcc\x05\x06\x0a\xbb\x05\x46\x5a\xcc\x05\x06\x0a\xbb\x05\x46" - /* 1760 */ "\x5a\xcc\x05\x06\x0a\xbb\x05\x46\x5a\xcc\x00\x00\x00\x00\x00\x00" - /* 1776 */ "\x00\x00\x00\x00\x03\x00\x00\x00\x44\x00\x00\x00\x33\x00\x22\x22" - /* 1792 */ "\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00\x33\x00\x22\x22" - /* 1808 */ "\x66\x00\x00\x00\x55\x00\x55\x55\xcc\x00\x00\x00\x03\x00\x02\x02" - /* 1824 */ "\x46\x00\x00\x00\x05\x00\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" - /* 1840 */ "\x46\x05\x5a\x5a\xcc\x05\x05\x05\x46\x05\x5a\x5a\xcc\x05\x05\x05" - /* 1856 */ "\x06\x05\x0a\x0a\xbb\x05\x05\x05\x46\x05\x5a\x5a\xcc\x05\x05\x05" - /* 1872 */ "\x06\x05\x0a\x0a\xbb\x05\x05\x05\x46\x05\x5a\x5a\xcc\x05\x05\x05" - /* 1888 */ "\x06\x05\x0a\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" - /* 1904 */ "\x05\x05\x05\x05\x05\x05\x05\x05\x05\x46\x05\x05\x05\x5a\x05\x5a" - /* 1920 */ "\x5a\xcc\x05\x05\x05\x05\x05\x05\x05\x46\x05\x05\x05\x5a\x05\x5a" - /* 1936 */ "\x5a\xcc\x05\x05\x05\x05\x05\x05\x05\x06\x05\x05\x05\x0a\x05\x0a" - /* 1952 */ "\x0a"; - -const unsigned char * const adv_gomoku /* [978] */ = (unsigned char*) - /* 0 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 16 */ "\x00\x00\x00\x00\xa0\x00\xa0\x00\x04\x00\x04\x00\x00\xd0\x00\xd0" - /* 32 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 48 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 64 */ "\x00\x70\x00\x00\x00\x00\xa0\x00\xa1\x00\x00\x00\xa0\x00\x04\x00" - /* 80 */ "\x04\x00\x00\x00\x04\x00\xd0\xd0\x00\xd0\x00\xd0\x00\xd0\x00\x00" - /* 96 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x70\x08\x08\x00\x08\x00\x08\x00" - /* 112 */ "\x08\x00\x08\x00\x40\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x00" - /* 128 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70" - /* 144 */ "\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\xa1\x00\x00\x00\xa1\x00" - /* 160 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 176 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 192 */ "\x00\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x00\x00" - /* 208 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 224 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 240 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x00\x00" - /* 256 */ "\x00\x70\x21\x00\x00\x00\x00\x00\x00\x00\xa0\x00\xa1\x00\x00\x00" - /* 272 */ "\xa1\x00\x00\x00\xa0\x00\x00\x00\xa0\x00\x04\x00\x04\x00\x00\x00" - /* 288 */ "\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\xd0\xd0\x00\xd0\x00\xd0" - /* 304 */ "\x00\xd0\x00\xd0\x00\xd0\x00\xd0\x00\xd0\x00\x00\x00\x00\x00\x00" - /* 320 */ "\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x70\x08\x08\x00" - /* 336 */ "\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00" - /* 352 */ "\x40\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40" - /* 368 */ "\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 384 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x00\x00\x00\x70" - /* 400 */ "\x21\x00\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\xa1\x00" - /* 416 */ "\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\xa1\x00\x00\x00\x00\x00" - /* 432 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 448 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 464 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 480 */ "\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00" - /* 496 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 512 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 528 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 544 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 560 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x00\x00\x00\x70\x21\x00" - /* 576 */ "\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x00\xa0\x00" - /* 592 */ "\xa1\x00\x00\x00\xa1\x00\x00\x00\xa0\x00\x00\x00\xa1\x00\x00\x00" - /* 608 */ "\xa0\x00\x00\x00\xa0\x00\x04\x00\x04\x00\x00\x00\x04\x00\x00\x00" - /* 624 */ "\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\xd0" - /* 640 */ "\x00\xd0\x00\x00\x00\xd0\x00\x00\x00\xd0\x00\x00\x00\xd0\x00\x00" - /* 656 */ "\x00\xd0\x00\x00\x00\xd0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 672 */ "\x70\x21\x00\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00" - /* 688 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 704 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 720 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 736 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 752 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 768 */ "\x00\x00\x00\x00\x00\x00\x00\x70\x00\x00\x00\x70\x21\x00\x00\x00" - /* 784 */ "\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x70\x00\x00\x00\x00" - /* 800 */ "\x00\x00\xa1\x00\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\xa1\x00" - /* 816 */ "\x00\x00\x00\x00\x00\x00\xa1\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 832 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 848 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 864 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 880 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x21" - /* 896 */ "\x00\x00\x00\x00\x00\x00\x70\x21\x00\x00\x00\x00\x00\x00\x00\x00" - /* 912 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 928 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 944 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 960 */ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - /* 976 */ "\x00"; - -/* name.c */ -word_t *toplev; - -/* friend.c */ -/* Ptt ¦UºØ¯S§O¦W³æªºÀɦW */ -char *friend_file[8] = { - FN_OVERRIDES, - FN_REJECT, - "alohaed", - "postlist", - "", /* may point to other filename */ - FN_CANVOTE, - FN_WATER, - FN_VISABLE -}; - -#ifdef NOKILLWATERBALL -char reentrant_write_request = 0; -#endif - -#ifdef PTTBBS_UTIL - #ifdef OUTTA_TIMER - #define COMMON_TIME (SHM->GV2.e.now) - #else - #define COMMON_TIME (time(0)) - #endif -#else - #define COMMON_TIME (now) -#endif diff --git a/mbbsd/vice.c b/mbbsd/vice.c deleted file mode 100644 index 14e4e8f4..00000000 --- a/mbbsd/vice.c +++ /dev/null @@ -1,153 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#define VICE_PLAY BBSHOME "/etc/vice/vice.play" -#define VICE_DATA "vice.new" -#define VICE_BINGO BBSHOME "/etc/vice.bingo" -#define VICE_SHOW BBSHOME "/etc/vice.show" -#define VICE_LOST BBSHOME "/etc/vice/vice.lost" -#define VICE_WIN BBSHOME "/etc/vice/vice.win" -#define VICE_END BBSHOME "/etc/vice/vice.end" -#define VICE_NO BBSHOME "/etc/vice/vice.no" -#define MAX_NO_PICTURE 2 -#define MAX_WIN_PICTURE 2 -#define MAX_LOST_PICTURE 3 -#define MAX_END_PICTURE 5 - -static int -vice_load(char tbingo[6][15]) -{ - FILE *fb = fopen(VICE_BINGO, "r"); - char buf[16], *ptr; - int i = 0; - if (!fb) - return -1; - bzero((char *)tbingo, 6*15); - while (i < 6 && fgets(buf, 15, fb)) { - if ((ptr = strchr(buf, '\n'))) - *ptr = 0; - strcpy(tbingo[i++], buf); - } - fclose(fb); - return 0; -} - -static int -check(char tbingo[6][15], const char *data) -{ - int i = 0, j; - - if (!strcmp(data, tbingo[0])) - return 8; - - for (j = 8; j > 0; j--) - for (i = 1; i < 6; i++) - if (!strncmp(data + 8 - j, tbingo[i] + 8 - j, j)) - return j - 1; - return 0; -} -/* TODO Ptt:showfile ran_showfile more ¤TªÌn¦X */ -static int -ran_showfile(int y, int x, const char *filename, int maxnum) -{ - FILE *fs; - char buf[512]; - - bzero(buf, sizeof(buf)); - snprintf(buf, sizeof(buf), "%s%d", filename, (int)(random() % maxnum + 1)); - if (!(fs = fopen(buf, "r"))) { - move(10, 10); - prints("can't open file: %s", buf); - return 0; - } - move(y, x); - - while (fgets(buf, sizeof(buf), fs)) - outs(buf); - - fclose(fs); - return 1; -} - -static int -ran_showmfile(const char *filename, int maxnum) -{ - char buf[256]; - - snprintf(buf, sizeof(buf), "%s%d", filename, (int)(random() % maxnum + 1)); - return more(buf, YEA); -} - - -int -vice_main(void) -{ - FILE *fd; - char tbingo[6][15]; - char buf_data[256], - serial[16], ch[2], *ptr; - int TABLE[] = {0, 10, 200, 1000, 4000, 10000, 40000, 100000, 200000}; - int total = 0, money, i = 4, j = 0; - - setuserfile(buf_data, VICE_DATA); - if (!dashf(buf_data)) { - ran_showmfile(VICE_NO, MAX_NO_PICTURE); - return 0; - } - if (vice_load(tbingo) < 0) - return -1; - clear(); - ran_showfile(0, 0, VICE_PLAY, 1); - ran_showfile(10, 0, VICE_SHOW, 1); - - if (!(fd = fopen(buf_data, "r"))) - return 0; - j = 0; - i = 0; - move(10, 24); - clrtoeol(); - outs("³o¤@´Áªºµo²¼¸¹½X"); - // FIXME ·íµo²¼¦h©ó¤@¦æ, ¶}¼úªº¸¹½X´N·|³Q»\±¼ - while (fgets(serial, 15, fd)) { - if ((ptr = strchr(serial, '\r'))) - *ptr = 0; - if (j == 0) - i++; - if( i >= 14 ) - break; - move(10 + i, 24 + j); - outs(serial); - j += 9; - j %= 45; - } - getdata(8, 0, "«ö'c'¶}©l¹ï¼ú¤F(©Î¬O¥ô·NÁäÂ÷¶})): ", - ch, sizeof(ch), LCECHO); - if (ch[0] != 'c' || lockutmpmode(VICE, LOCK_MULTI)) { - fclose(fd); - return 0; - } - showtitle("µo²¼¹ï¼ú", BBSNAME); - rewind(fd); - while (fgets(serial, 15, fd)) { - if ((ptr = strchr(serial, '\n'))) - *ptr = 0; - money = TABLE[check(tbingo, serial)]; - total += money; - prints("%s ¤¤¤F %d\n", serial, money); - } - pressanykey(); - if (total > 0) { - ran_showmfile(VICE_WIN, MAX_WIN_PICTURE); - move(22, 0); - clrtoeol(); - prints("¥þ³¡ªºµo²¼¤¤¤F %d ¶ô¿ú\n", total); - demoney(total); - } else - ran_showmfile(VICE_LOST, MAX_LOST_PICTURE); - - fclose(fd); - unlink(buf_data); - pressanykey(); - unlockutmpmode(); - return 0; -} diff --git a/mbbsd/vote.c b/mbbsd/vote.c deleted file mode 100644 index 7562a7b8..00000000 --- a/mbbsd/vote.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#define MAX_VOTE_NR 20 -#define MAX_VOTE_PAGE 5 -#define ITEM_PER_PAGE 30 - -const char * const STR_bv_control = "control"; /* §ë²¼¤é´Á ¿ï¶µ */ -const char * const STR_bv_desc = "desc"; /* §ë²¼¥Øªº */ -const char * const STR_bv_ballots = "ballots"; /* §ëªº²¼ (per byte) */ -const char * const STR_bv_flags = "flags"; -const char * const STR_bv_comments = "comments"; /* §ë²¼ªÌªº«Øij */ -const char * const STR_bv_limited = "limited"; /* ¨p¤H§ë²¼ */ -const char * const STR_bv_limits = "limits"; /* §ë²¼¸ê®æ¨î */ -const char * const STR_bv_title = "vtitle"; - -const char * const STR_bv_results = "results"; - -typedef struct { - char control[sizeof("controlXX\0")]; - char desc[sizeof("descXX\0")]; - char ballots[sizeof("ballotsXX\0")]; - char flags[sizeof("flagsXX\0")]; - char comments[sizeof("commentsXX\0")]; - char limited[sizeof("limitedXX\0")]; - char limits[sizeof("limitsXX\0")]; - char title[sizeof("vtitleXX\0")]; -} vote_buffer_t; - -void -b_suckinfile(FILE * fp, char *fname) -{ - FILE *sfp; - - if ((sfp = fopen(fname, "r"))) { - char inbuf[256]; - - while (fgets(inbuf, sizeof(inbuf), sfp)) - fputs(inbuf, fp); - fclose(sfp); - } -} - -void -b_suckinfile_invis(FILE * fp, char *fname, const char *boardname) -{ - FILE *sfp; - - if ((sfp = fopen(fname, "r"))) { - char inbuf[256]; - if(fgets(inbuf, sizeof(inbuf), sfp)) - { - /* first time, try if boardname revealed. */ - char *post = strstr(inbuf, str_post1); - if(!post) post = strstr(inbuf, str_post2); - if(post) - post = strstr(post, boardname); - if(post) { - /* found releaved stuff. */ - /* - // mosaic method 1 - while(*boardname++) - *post++ = '?'; - */ - // mosaic method 2 - strcpy(post, "(¬YÁô§Î¬ÝªO)\n"); - } - fputs(inbuf, fp); - while (fgets(inbuf, sizeof(inbuf), sfp)) - fputs(inbuf, fp); - } - fclose(sfp); - } -} - -static void -b_count(const char *buf, int counts[], short item_num, int *total) -{ - short choice; - int fd; - - memset(counts, 0, item_num * sizeof(counts[0])); - *total = 0; - if ((fd = open(buf, O_RDONLY)) != -1) { - flock(fd, LOCK_EX); /* Thor: ¨¾¤î¦h¤H¦P®Éºâ */ - while (read(fd, &choice, sizeof(short)) == sizeof(short)) { - if (choice >= item_num) - continue; - counts[choice]++; - (*total)++; - } - flock(fd, LOCK_UN); - close(fd); - } -} - - -static int -b_nonzeroNum(const char *buf) -{ - int i = 0; - char inchar; - int fd; - - if ((fd = open(buf, O_RDONLY)) != -1) { - while (read(fd, &inchar, 1) == 1) - if (inchar) - i++; - close(fd); - } - return i; -} - -static void -vote_report(const char *bname, const char *fname, char *fpath) -{ - register char *ip; - time4_t dtime; - int fd, bid; - fileheader_t header; - - ip = fpath; - while (*(++ip)); - *ip++ = '/'; - - /* get a filename by timestamp */ - - dtime = now; - for (;;) { - sprintf(ip, "M.%d.A", (int)++dtime); - fd = open(fpath, O_CREAT | O_EXCL | O_WRONLY, 0644); - if (fd >= 0) - break; - dtime++; - } - close(fd); - - unlink(fpath); - link(fname, fpath); - - /* append record to .DIR */ - - memset(&header, 0, sizeof(fileheader_t)); - strlcpy(header.owner, "[°¨¸ô±´¤l]", sizeof(header.owner)); - snprintf(header.title, sizeof(header.title), "[%s] ¬ÝªO ¿ï±¡³ø¾É", bname); - { - register struct tm *ptime = localtime4(&dtime); - - snprintf(header.date, sizeof(header.date), - "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); - } - strlcpy(header.filename, ip, sizeof(header.filename)); - - strcpy(ip, FN_DIR); - if ((fd = open(fpath, O_WRONLY | O_CREAT, 0644)) >= 0) { - flock(fd, LOCK_EX); - lseek(fd, 0, SEEK_END); - write(fd, &header, sizeof(fileheader_t)); - flock(fd, LOCK_UN); - close(fd); - if ((bid = getbnum(bname)) > 0) - setbtotal(bid); - - } -} - -static void -b_result_one(vote_buffer_t *vbuf, boardheader_t * fh, int ind, int *total) -{ - FILE *cfp, *tfp, *frp, *xfp; - char *bname; - char buf[STRLEN]; - char inbuf[80]; - int *counts; - int people_num; - short item_num, junk; - char b_control[64]; - char b_newresults[64]; - char b_report[64]; - time4_t closetime; - - fh->bvote--; - - snprintf(vbuf->ballots, sizeof(vbuf->ballots), "%s%d", STR_bv_ballots, ind); - snprintf(vbuf->control, sizeof(vbuf->control),"%s%d", STR_bv_control, ind); - snprintf(vbuf->desc, sizeof(vbuf->desc), "%s%d", STR_bv_desc, ind); - snprintf(vbuf->flags, sizeof(vbuf->flags), "%s%d", STR_bv_flags, ind); - snprintf(vbuf->comments, sizeof(vbuf->comments), "%s%d", STR_bv_comments, ind); - snprintf(vbuf->limited, sizeof(vbuf->limited), "%s%d", STR_bv_limited, ind); - snprintf(vbuf->limits, sizeof(vbuf->limits), "%s%d", STR_bv_limits, ind); - snprintf(vbuf->title, sizeof(vbuf->title), "%s%d", STR_bv_title, ind); - - bname = fh->brdname; - - setbfile(buf, bname, vbuf->control); - cfp = fopen(buf, "r"); - assert(cfp); - fscanf(cfp, "%hd,%hd\n%d\n", &item_num, &junk, &closetime); - fclose(cfp); - - // prevent death caused by a bug, it should be remove later. - if (item_num <= 0) - return; - - counts = (int *)malloc(item_num * sizeof(int)); - - setbfile(b_control, bname, "tmp"); - if (rename(buf, b_control) == -1) - return; - setbfile(buf, bname, vbuf->flags); - people_num = b_nonzeroNum(buf); - unlink(buf); - setbfile(buf, bname, vbuf->ballots); - b_count(buf, counts, item_num, total); - unlink(buf); - - setbfile(b_newresults, bname, "newresults"); - if ((tfp = fopen(b_newresults, "w")) == NULL) - return; - - setbfile(buf, bname, vbuf->title); - - if ((xfp = fopen(buf, "r"))) { - fgets(inbuf, sizeof(inbuf), xfp); - fprintf(tfp, "%s\n¡» §ë²¼¦WºÙ: %s\n\n", msg_seperator, inbuf); - fclose(xfp); - } - fprintf(tfp, "%s\n¡» §ë²¼¤¤¤î©ó: %s\n\n¡» ²¼¿ïÃD¥Ø´yz:\n\n", - msg_seperator, ctime4(&closetime)); - fh->vtime = now; - - setbfile(buf, bname, vbuf->desc); - - b_suckinfile(tfp, buf); - unlink(buf); - - if ((cfp = fopen(b_control, "r"))) { - fgets(inbuf, sizeof(inbuf), cfp); - fgets(inbuf, sizeof(inbuf), cfp); - fprintf(tfp, "\n¡»§ë²¼µ²ªG:(¦@¦³ %d ¤H§ë²¼,¨C¤H³Ì¦h¥i§ë %hd ²¼)\n", - people_num, junk); - fprintf(tfp, " ¿ï ¶µ Á`²¼¼Æ ±o²¼²v ±o²¼¤À¥¬\n"); - for (junk = 0; junk < item_num; junk++) { - fgets(inbuf, sizeof(inbuf), cfp); - chomp(inbuf); - fprintf(tfp, " %-42s %3d ²¼ %6.2f%% %6.2f%%\n", inbuf + 3, counts[junk], - (float)(counts[junk] * 100) / (float)(people_num), - (float)(counts[junk] * 100) / (float)(*total)); - } - fclose(cfp); - } - unlink(b_control); - free(counts); - - fprintf(tfp, "%s\n¡» ¨Ï¥ÎªÌ«Øij¡G\n\n", msg_seperator); - setbfile(buf, bname, vbuf->comments); - b_suckinfile(tfp, buf); - unlink(buf); - - fprintf(tfp, "%s\n¡» Á`²¼¼Æ = %d ²¼\n\n", msg_seperator, *total); - fclose(tfp); - - setbfile(b_report, bname, "report"); - if ((frp = fopen(b_report, "w"))) { - b_suckinfile(frp, b_newresults); - fclose(frp); - } - setbpath(inbuf, bname); - vote_report(bname, b_report, inbuf); - if (!(fh->brdattr & (BRD_NOCOUNT|BRD_HIDE))) { // from ptt2 local modification - setbpath(inbuf, "Record"); - vote_report(bname, b_report, inbuf); - } - unlink(b_report); - - tfp = fopen(b_newresults, "a"); - setbfile(buf, bname, STR_bv_results); - b_suckinfile(tfp, buf); - fclose(tfp); - Rename(b_newresults, buf); -} - -static void -b_result(vote_buffer_t *vbuf, boardheader_t * fh) -{ - FILE *cfp; - time4_t closetime; - int i, total; - char buf[STRLEN]; - char temp[STRLEN]; - - for (i = 0; i < MAX_VOTE_NR; i++) { - snprintf(vbuf->control, sizeof(vbuf->control), "%s%d", STR_bv_control, i); - - setbfile(buf, fh->brdname, vbuf->control); - cfp = fopen(buf, "r"); - if (!cfp) - continue; - fgets(temp, sizeof(temp), cfp); - fscanf(cfp, "%d\n", &closetime); - fclose(cfp); - if (closetime < now) - b_result_one(vbuf, fh, i, &total); - } -} - -static int -b_close(boardheader_t * fh, vote_buffer_t *vbuf) -{ - b_result(vbuf, fh); - return 1; -} - -static int -b_closepolls(void) -{ - boardheader_t *fhp; - int pos; - vote_buffer_t vbuf; - -#ifndef BARRIER_HAS_BEEN_IN_SHM - char *fn_vote_polling = ".polling"; - unsigned long last; - FILE *cfp; - /* XXX necessary to lock ? */ - if ((cfp = fopen(fn_vote_polling, "r"))) { - char timebuf[100]; - fgets(timebuf, sizeof(timebuf), cfp); - sscanf(timebuf, "%lu", &last); - fclose(cfp); - if (last + 3600 >= (unsigned long)now) - return 0; - } - if ((cfp = fopen(fn_vote_polling, "w")) == NULL) - return 0; - fprintf(cfp, "%d\n%s\n", now, ctime4(&now)); - fclose(cfp); -#endif - - for (fhp = bcache, pos = 1; pos <= numboards; fhp++, pos++) { - if (fhp->bvote && b_close(fhp, &vbuf)) { - if (substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) - outs(err_board_update); - else - reset_board(pos); - } - } - - return 0; -} - -void -auto_close_polls(void) -{ - /* ³Ì¦h¤@¤Ñ¶}²¼¤@¦¸ */ - if (now - SHM->close_vote_time > 86400) { - b_closepolls(); - SHM->close_vote_time = now; - } -} - -static int -vote_view(vote_buffer_t *vbuf, const char *bname, int vote_index) -{ - boardheader_t *fhp; - FILE *fp; - char buf[STRLEN], genbuf[STRLEN], inbuf[STRLEN]; - short item_num, i; - int num = 0, pos, *counts, total; - time4_t closetime; - - snprintf(vbuf->ballots, sizeof(vbuf->ballots),"%s%d", STR_bv_ballots, vote_index); - snprintf(vbuf->control, sizeof(vbuf->control), "%s%d", STR_bv_control, vote_index); - snprintf(vbuf->desc, sizeof(vbuf->desc), "%s%d", STR_bv_desc, vote_index); - snprintf(vbuf->flags, sizeof(vbuf->flags), "%s%d", STR_bv_flags, vote_index); - snprintf(vbuf->comments, sizeof(vbuf->comments), "%s%d", STR_bv_comments, vote_index); - snprintf(vbuf->limited, sizeof(vbuf->limited), "%s%d", STR_bv_limited, vote_index); - snprintf(vbuf->limits, sizeof(vbuf->limits), "%s%d", STR_bv_limits, vote_index); - snprintf(vbuf->title, sizeof(vbuf->title), "%s%d", STR_bv_title, vote_index); - - setbfile(buf, bname, vbuf->ballots); - if ((num = dashs(buf)) < 0) /* file size */ - num = 0; - - setbfile(buf, bname, vbuf->title); - move(0, 0); - clrtobot(); - - if ((fp = fopen(buf, "r"))) { - fgets(inbuf, sizeof(inbuf), fp); - prints("\n§ë²¼¦WºÙ: %s", inbuf); - fclose(fp); - } - setbfile(buf, bname, vbuf->control); - fp = fopen(buf, "r"); - - assert(fp); - fscanf(fp, "%hd,%hd\n%d\n", &item_num, &i, &closetime); - counts = (int *)malloc(item_num * sizeof(int)); - - prints("\n¡» ¹wª¾§ë²¼¬ö¨Æ: ¨C¤H³Ì¦h¥i§ë %d ²¼,¥Ø«e¦@¦³ %d ²¼,\n" - "¥»¦¸§ë²¼±Nµ²§ô©ó %s", atoi(inbuf), (int)(num / sizeof(short)), - ctime4(&closetime)); - - /* Thor: ¶}©ñ ²¼¼Æ ¹wª¾ */ - setbfile(buf, bname, vbuf->flags); - prints("¦@¦³ %d ¤H§ë²¼\n", b_nonzeroNum(buf)); - - setbfile(buf, bname, vbuf->ballots); - b_count(buf, counts, item_num, &total); - - total = 0; - - for (i = num = 0; i < item_num; i++, num++) { - fgets(inbuf, sizeof(inbuf), fp); - chomp(inbuf); - inbuf[30] = '\0'; /* truncate */ - move(num % 15 + 6, num / 15 * 40); - prints(" %-32s%3d ²¼", inbuf, counts[i]); - total += counts[i]; - if (num == 29) { - num = -1; - pressanykey(); - move(6, 0); - clrtobot(); - } - } - fclose(fp); - free(counts); - pos = getbnum(bname); - assert(0<=pos-1 && pos-1<MAX_BOARD); - fhp = bcache + pos - 1; - move(t_lines - 3, 0); - prints("¡» ¥Ø«eÁ`²¼¼Æ = %d ²¼", total); - getdata(b_lines - 1, 0, "(A)¨ú®ø§ë²¼ (B)´£¦¶}²¼ (C)Ä~Äò¡H[C] ", genbuf, - 4, LCECHO); - if (genbuf[0] == 'a') { - getdata(b_lines - 1, 0, "½Ð¦A¦¸½T»{¨ú®ø§ë²¼ (Y/N) [N] ", genbuf, - 4, LCECHO); - if (genbuf[0] == 'n') - return FULLUPDATE; - - setbfile(buf, bname, vbuf->control); - unlink(buf); - setbfile(buf, bname, vbuf->flags); - unlink(buf); - setbfile(buf, bname, vbuf->ballots); - unlink(buf); - setbfile(buf, bname, vbuf->desc); - unlink(buf); - setbfile(buf, bname, vbuf->limited); - unlink(buf); - setbfile(buf, bname, vbuf->limits); - unlink(buf); - setbfile(buf, bname, vbuf->title); - unlink(buf); - - fhp->bvote--; - - if (substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) - outs(err_board_update); - reset_board(pos); - } else if (genbuf[0] == 'b') { - b_result_one(vbuf, fhp, vote_index, &total); - if (substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) - outs(err_board_update); - - reset_board(pos); - } - return FULLUPDATE; -} - -static int -vote_view_all(vote_buffer_t *vbuf, const char *bname) -{ - int i; - int x = -1; - FILE *fp, *xfp; - char buf[STRLEN], genbuf[STRLEN]; - char inbuf[80]; - - move(0, 0); - for (i = 0; i < MAX_VOTE_NR; i++) { - snprintf(vbuf->control, sizeof(vbuf->control), "%s%d", STR_bv_control, i); - snprintf(vbuf->title, sizeof(vbuf->title), "%s%d", STR_bv_title, i); - setbfile(buf, bname, vbuf->control); - if ((fp = fopen(buf, "r"))) { - prints("(%d) ", i); - x = i; - fclose(fp); - - setbfile(buf, bname, vbuf->title); - if ((xfp = fopen(buf, "r"))) { - fgets(inbuf, sizeof(inbuf), xfp); - fclose(xfp); - } else - strlcpy(inbuf, "µL¼ÐÃD", sizeof(inbuf)); - prints("%s\n", inbuf); - } - } - - if (x < 0) - return FULLUPDATE; - snprintf(buf, sizeof(buf), "n¬Ý´X¸¹§ë²¼ [%d] ", x); - - getdata(b_lines - 1, 0, buf, genbuf, 4, LCECHO); - - - if (atoi(genbuf) < 0 || atoi(genbuf) > MAX_VOTE_NR) - snprintf(genbuf, sizeof(genbuf), "%d", x); - snprintf(vbuf->control, sizeof(vbuf->control), "%s%d", STR_bv_control, atoi(genbuf)); - - setbfile(buf, bname, vbuf->control); - - if (dashf(buf)) { - return vote_view(vbuf, bname, atoi(genbuf)); - } else - return FULLUPDATE; -} - -static int -vote_maintain(const char *bname) -{ - FILE *fp = NULL; - char inbuf[STRLEN], buf[STRLEN]; - int num = 0, aborted, pos, x, i; - time4_t closetime; - boardheader_t *fhp; - char genbuf[4]; - vote_buffer_t vbuf; - - if (!(currmode & MODE_BOARD)) - return 0; - if ((pos = getbnum(bname)) <= 0) - return 0; - - assert(0<=pos-1 && pos-1<MAX_BOARD); - fhp = bcache + pos - 1; - - if (fhp->bvote != 0) { - -#if 0 // convert the filenames of first vote - convert_first_vote(fhp); -#endif - getdata(b_lines - 1, 0, - "(V)Æ[¹î¥Ø«e§ë²¼ (M)Á|¿ì·s§ë²¼ (A)¨ú®ø©Ò¦³§ë²¼ (Q)Ä~Äò [Q]", - genbuf, 4, LCECHO); - if (genbuf[0] == 'v') - return vote_view_all(&vbuf, bname); - else if (genbuf[0] == 'a') { - fhp->bvote = 0; - - for (i = 0; i < MAX_VOTE_NR; i++) { - int j; - char buf2[64]; - const char *filename[] = { - STR_bv_ballots, STR_bv_control, STR_bv_desc, STR_bv_desc, - STR_bv_flags, STR_bv_comments, STR_bv_limited, STR_bv_limits, - STR_bv_title, NULL - }; - for (j = 0; filename[j] != NULL; j++) { - snprintf(buf2, sizeof(buf2), "%s%d", filename[j], i); - setbfile(buf, bname, buf2); - unlink(buf); - } - } - if (substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) - outs(err_board_update); - - return FULLUPDATE; - } else if (genbuf[0] != 'm') { - if (fhp->bvote >= MAX_VOTE_NR) - vmsg("¤£±oÁ|¿ì¹L¦h§ë²¼"); - return FULLUPDATE; - } - } - - x = 1; - do { - snprintf(vbuf.control, sizeof(vbuf.control), "%s%d", STR_bv_control, x); - setbfile(buf, bname, vbuf.control); - x++; - } while (dashf(buf) && x <= MAX_VOTE_NR); - - --x; - if (x >= MAX_VOTE_NR) - return FULLUPDATE; - - getdata(b_lines - 1, 0, - "½T©wnÁ|¿ì§ë²¼¶Ü¡H [y/N]: ", - inbuf, 4, LCECHO); - if (inbuf[0] != 'y') - return FULLUPDATE; - - stand_title("Á|¿ì§ë²¼"); - snprintf(vbuf.ballots, sizeof(vbuf.ballots), "%s%d", STR_bv_ballots, x); - snprintf(vbuf.control, sizeof(vbuf.control), "%s%d", STR_bv_control, x); - snprintf(vbuf.desc, sizeof(vbuf.desc), "%s%d", STR_bv_desc, x); - snprintf(vbuf.flags, sizeof(vbuf.flags), "%s%d", STR_bv_flags, x); - snprintf(vbuf.comments, sizeof(vbuf.comments), "%s%d", STR_bv_comments, x); - snprintf(vbuf.limited, sizeof(vbuf.limited), "%s%d", STR_bv_limited, x); - snprintf(vbuf.limits, sizeof(vbuf.limits), "%s%d", STR_bv_limits, x); - snprintf(vbuf.title, sizeof(vbuf.title), "%s%d", STR_bv_title, x); - - clear(); - move(0, 0); - prints("²Ä %d ¸¹§ë²¼\n", x); - setbfile(buf, bname, vbuf.title); - getdata(4, 0, "½Ð¿é¤J§ë²¼¦WºÙ:", inbuf, 50, LCECHO); - if (inbuf[0] == '\0') - strlcpy(inbuf, "¤£ª¾¦Wªº", sizeof(inbuf)); - fp = fopen(buf, "w"); - assert(fp); - fputs(inbuf, fp); - fclose(fp); - - vmsg("«ö¥ô¦óÁä¶}©l½s¿è¦¹¦¸ [§ë²¼©v¦®]"); - setbfile(buf, bname, vbuf.desc); - aborted = vedit(buf, NA, NULL); - if (aborted == -1) { - vmsg("¨ú®ø¦¹¦¸§ë²¼"); - return FULLUPDATE; - } - aborted = 0; - setbfile(buf, bname, vbuf.flags); - unlink(buf); - - getdata(4, 0, - "¬O§_©w§ë²¼ªÌ¦W³æ¡G(y)½s¿è¥i§ë²¼¤Hû¦W³æ[n]¥ô¦ó¤H¬Ò¥i§ë²¼:[N]", - inbuf, 2, LCECHO); - setbfile(buf, bname, vbuf.limited); - if (inbuf[0] == 'y') { - fp = fopen(buf, "w"); - assert(fp); - //fprintf(fp, "¦¹¦¸§ë²¼³]"); - fclose(fp); - friend_edit(FRIEND_CANVOTE); - } else { - if (dashf(buf)) - unlink(buf); - } - getdata(5, 0, - "¬O§_©w§ë²¼¸ê®æ¡G(y)¨î§ë²¼¸ê®æ[n]¤£³]:[N]", - inbuf, 2, LCECHO); - setbfile(buf, bname, vbuf.limits); - if (inbuf[0] == 'y') { - fp = fopen(buf, "w"); - assert(fp); - do { - getdata(6, 0, "µù¥U®É¶¡¨î (¥H'¤ë'¬°³æ¦ì¡A0~120)¡G", inbuf, 4, DOECHO); - closetime = atoi(inbuf); // borrow variable - } while (closetime < 0 || closetime > 120); - fprintf(fp, "%d\n", now - (2592000 * closetime)); - do { - getdata(6, 0, "¤W¯¸¦¸¼Æ¤U", inbuf, 6, DOECHO); - closetime = atoi(inbuf); // borrow variable - } while (closetime < 0); - fprintf(fp, "%d\n", closetime); - do { - getdata(6, 0, "¤å³¹½g¼Æ¤U", inbuf, 6, DOECHO); - closetime = atoi(inbuf); // borrow variable - } while (closetime < 0); - fprintf(fp, "%d\n", closetime); - fclose(fp); - } else { - if (dashf(buf)) - unlink(buf); - } - clear(); - getdata(0, 0, "¦¹¦¸§ë²¼¶i¦æ´X¤Ñ (¤@¨ì¤T¤Q¤Ñ)¡H", inbuf, 4, DOECHO); - - closetime = atoi(inbuf); - if (closetime <= 0) - closetime = 1; - else if (closetime > 30) - closetime = 30; - - closetime = closetime * 86400 + now; - setbfile(buf, bname, vbuf.control); - fp = fopen(buf, "w"); - assert(fp); - fprintf(fp, "000,000\n%d\n", closetime); - - outs("\n½Ð¨Ì§Ç¿é¤J¿ï¶µ, «ö ENTER §¹¦¨³]©w"); - num = 0; - x = 0; /* x is the page number */ - while (!aborted) { - if( num % 15 == 0 ){ - for( i = num ; i < num + 15 ; ++i ){ - move((i % 15) + 2, (i / 15) * 40); - prints(ANSI_COLOR(1;30) "%c)" ANSI_RESET " ", i + 'A'); - } - } - snprintf(buf, sizeof(buf), "%c) ", num + 'A'); - getdata((num % 15) + 2, (num / 15) * 40, buf, - inbuf, 37, DOECHO); - if (*inbuf) { - fprintf(fp, "%1c) %s\n", (num + 'A'), inbuf); - num++; - } - if ((*inbuf == '\0' && num >= 1) || x == MAX_VOTE_PAGE) - aborted = 1; - if (num == ITEM_PER_PAGE) { - x++; - num = 0; - } - } - snprintf(buf, sizeof(buf), "½Ð°Ý¨C¤H³Ì¦h¥i§ë´X²¼¡H([1]¡ã%d): ", x * ITEM_PER_PAGE + num); - - getdata(t_lines - 3, 0, buf, inbuf, 3, DOECHO); - - if (atoi(inbuf) <= 0 || atoi(inbuf) > (x * ITEM_PER_PAGE + num)) { - inbuf[0] = '1'; - inbuf[1] = 0; - } - - rewind(fp); - fprintf(fp, "%3d,%3d\n", x * ITEM_PER_PAGE + num, MAX(1, atoi(inbuf))); - fclose(fp); - - fhp->bvote++; - - if (substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) - outs(err_board_update); - reset_board(pos); - outs("¶}©l§ë²¼¤F¡I"); - - return FULLUPDATE; -} - -static int -vote_flag(vote_buffer_t *vbuf, const char *bname, int index, char val) -{ - char buf[256], flag; - int fd, num, size; - - snprintf(vbuf->flags, sizeof(vbuf->flags), "%s%d", STR_bv_flags, index); - - num = usernum - 1; - setbfile(buf, bname, vbuf->flags); - if ((fd = open(buf, O_RDWR | O_CREAT, 0600)) == -1) - return -1; - size = lseek(fd, 0, SEEK_END); - memset(buf, 0, sizeof(buf)); - while (size <= num) { - write(fd, buf, sizeof(buf)); - size += sizeof(buf); - } - lseek(fd, num, SEEK_SET); - read(fd, &flag, 1); - if (flag == 0 && val != 0) { - lseek(fd, num, SEEK_SET); - write(fd, &val, 1); - } - close(fd); - return flag; -} - -static int -user_vote_one(vote_buffer_t *vbuf, const char *bname, int ind) -{ - FILE *cfp, *fcm; - char buf[STRLEN], redo; - boardheader_t *fhp; - short count, tickets; - short curr_page, item_num, max_page; - char inbuf[80], choices[ITEM_PER_PAGE+1], vote[4], *chosen; - time4_t closetime; - - // pos = boaord id, must be at least one int. - // fd should be int. - int pos = 0, i = 0; - int fd = 0; - - snprintf(vbuf->ballots, sizeof(vbuf->ballots), "%s%d", STR_bv_ballots, ind); - snprintf(vbuf->control, sizeof(vbuf->control), "%s%d", STR_bv_control, ind); - snprintf(vbuf->desc, sizeof(vbuf->desc), "%s%d", STR_bv_desc, ind); - snprintf(vbuf->flags, sizeof(vbuf->flags),"%s%d", STR_bv_flags, ind); - snprintf(vbuf->comments, sizeof(vbuf->comments), "%s%d", STR_bv_comments, ind); - snprintf(vbuf->limited, sizeof(vbuf->limited), "%s%d", STR_bv_limited, ind); - snprintf(vbuf->limits, sizeof(vbuf->limits), "%s%d", STR_bv_limits, ind); - - setbfile(buf, bname, vbuf->control); - cfp = fopen(buf, "r"); - if (!cfp) - return FULLUPDATE; - - setbfile(buf, bname, vbuf->limited); /* Ptt */ - if (dashf(buf)) { - setbfile(buf, bname, FN_CANVOTE); - if (!belong(buf, cuser.userid)) { - fclose(cfp); - vmsg("¹ï¤£°_! ³o¬O¨p¤H§ë²¼..§A¨Ã¨S¦³¨üÁÜò!"); - return FULLUPDATE; - } else { - vmsg("®¥³ß§A¨üÁܦ¹¦¸¨p¤H§ë²¼. <À˵ø¦¹¦¸¨üÁܦW³æ>"); - more(buf, YEA); - } - } - setbfile(buf, bname, vbuf->limits); - if (dashf(buf)) { - int limits_logins, limits_posts; - FILE * lfp = fopen(buf, "r"); - assert(lfp); - fscanf(lfp, "%d", &closetime); - fscanf(lfp, "%d", &limits_logins); - fscanf(lfp, "%d", &limits_posts); - fclose(lfp); - if (cuser.firstlogin > closetime || cuser.numposts < limits_posts || - cuser.numlogins < limits_logins) { - vmsg("§A¤£°÷¸ê²`³á¡I"); - return FULLUPDATE; - } - } - if (vote_flag(vbuf, bname, ind, '\0')) { - vmsg("¦¹¦¸§ë²¼¡A§A¤w§ë¹L¤F¡I"); - return FULLUPDATE; - } - setutmpmode(VOTING); - setbfile(buf, bname, vbuf->desc); - more(buf, YEA); - - stand_title("§ë²¼½c"); - if ((pos = getbnum(bname)) <= 0) - return 0; - - assert(0<=pos-1 && pos-1<MAX_BOARD); - fhp = bcache + pos - 1; - - assert(cfp); - fscanf(cfp, "%hd,%hd\n%d\n", &item_num, &tickets, &closetime); - chosen = (char *)malloc(item_num+100); // XXX dirty fix ªO¥D¼W¥[¿ï¶µªº°ÝÃD - memset(chosen, 0, item_num+100); - memset(choices, 0, sizeof(choices)); - max_page = (item_num - 1)/ ITEM_PER_PAGE + 1; - - outs("§ë²¼¤è¦¡¡G½T©w¦n±zªº¿ï¾Ü«á¡A¿é¤J¨ä¥N½X(A, B, C...)§Y¥i¡C\n"); - prints("¦¹¦¸§ë²¼§A¥i¥H§ë %1hd ²¼¡C«ö 0 ¨ú®ø§ë²¼, 1 §¹¦¨§ë²¼, " - "> ¤U¤@¶, < ¤W¤@¶\n¦¹¦¸§ë²¼±Nµ²§ô©ó¡G%s \n", - tickets, ctime4(&closetime)); - -#define REDO_DRAW 1 -#define REDO_SCAN 2 - redo = REDO_DRAW; - curr_page = 0; - while (1) { - - if (redo) { - int i, j; - move(5, 0); - clrtobot(); - - /* ·Q¤£¨ì¦n¤èªk ¦]¬°¤£·Q¾ãÓŪ¶i memory - * ¦Ó¥B¤j³¡¤Àªº§ë²¼¤£·|¶W¹L¤@¶ ©Ò¥H¦A±qÀÉ®× scan */ - /* XXX §ë¨ì¤@¥bªO¥D¼W¥[¿ï¶µ«h chosen ¤Ó¤p */ - if (redo & REDO_SCAN) { - for (i = 0; i < curr_page; i++) - for (j = 0; j < ITEM_PER_PAGE; j++) - fgets(inbuf, sizeof(inbuf), cfp); - } - - count = 0; - for (i = 0; i < ITEM_PER_PAGE && fgets(inbuf, sizeof(inbuf), cfp); i++) { - chomp(inbuf); - move((count % 15) + 5, (count / 15) * 40); - prints("%c%s", chosen[curr_page * ITEM_PER_PAGE + i] ? '*' : ' ', - inbuf); - choices[count % ITEM_PER_PAGE] = inbuf[0]; - count++; - } - redo = 0; - } - - vote[0] = vote[1] = '\0'; - move(t_lines - 2, 0); - prints("§AÁÙ¥i¥H§ë %2d ²¼ [ ¥Ø«e©Ò¦b¶¼Æ %2d / ¦@ %2d ¶ (¥i¿é¤J '<' '>' ´«¶) ]", tickets - i, curr_page + 1, max_page); - getdata(t_lines - 4, 0, "¿é¤J±zªº¿ï¾Ü: ", vote, sizeof(vote), DOECHO); - *vote = toupper(*vote); - -#define CURRENT_CHOICE \ - chosen[curr_page * ITEM_PER_PAGE + vote[0] - 'A'] - if (vote[0] == '0' || (!vote[0] && !i)) { - outs("°O±o¦A¨Ó§ë³á!!"); - break; - } else if (vote[0] == '1' && i); - else if (!vote[0]) - continue; - else if (vote[0] == '<' && max_page > 1) { - curr_page = (curr_page + max_page - 1) % max_page; - rewind(cfp); - fgets(inbuf, sizeof(inbuf), cfp); - fgets(inbuf, sizeof(inbuf), cfp); - redo = REDO_DRAW | REDO_SCAN; - continue; - } - else if (vote[0] == '>' && max_page > 1) { - curr_page = (curr_page + 1) % max_page; - if (curr_page == 0) { - rewind(cfp); - fgets(inbuf, sizeof(inbuf), cfp); - fgets(inbuf, sizeof(inbuf), cfp); - } - redo = REDO_DRAW; - continue; - } - else if (index(choices, vote[0]) == NULL) /* µL®Ä */ - continue; - else if ( CURRENT_CHOICE ) { /* ¤w¿ï */ - move(((vote[0] - 'A') % 15) + 5, (((vote[0] - 'A')) / 15) * 40); - outc(' '); - CURRENT_CHOICE = 0; - i--; - continue; - } else { - if (i == tickets) - continue; - move(((vote[0] - 'A') % 15) + 5, (((vote[0] - 'A')) / 15) * 40); - outc('*'); - CURRENT_CHOICE = 1; - i++; - continue; - } - - if (vote_flag(vbuf, bname, ind, vote[0]) != 0) - outs("«½Æ§ë²¼! ¤£¤©p²¼¡C"); - else { - setbfile(buf, bname, vbuf->ballots); - if ((fd = open(buf, O_WRONLY | O_CREAT | O_APPEND, 0600)) == 0) - outs("µLªk§ë¤J²¼Ôo\n"); - else { - struct stat statb; - char buf[3], mycomments[3][74], b_comments[80]; - - for (i = 0; i < 3; i++) - strlcpy(mycomments[i], "\n", sizeof(mycomments[i])); - - flock(fd, LOCK_EX); - for (count = 0; count < item_num; count++) { - if (chosen[count]) - write(fd, &count, sizeof(short)); - } - flock(fd, LOCK_UN); - fstat(fd, &statb); - close(fd); - getdata(b_lines - 2, 0, - "±z¹ï³o¦¸§ë²¼¦³¤°»òÄ_¶Qªº·N¨£¶Ü¡H(y/n)[N]", - buf, 3, DOECHO); - if (buf[0] == 'Y' || buf[0] == 'y') { - do { - move(5, 0); - clrtobot(); - outs("½Ð°Ý±z¹ï³o¦¸§ë²¼¦³¤°»òÄ_¶Qªº·N¨£¡H" - "³Ì¦h¤T¦æ¡A«ö[Enter]µ²§ô"); - for (i = 0; (i < 3) && - getdata(7 + i, 0, "¡G", - mycomments[i], sizeof(mycomments[i]), - DOECHO); i++); - getdata(b_lines - 2, 0, "(S)Àx¦s (E)«·s¨Ó¹L " - "(Q)¨ú®ø¡H[S]", buf, 3, LCECHO); - } while (buf[0] == 'E' || buf[0] == 'e'); - if (buf[0] == 'Q' || buf[0] == 'q') - break; - setbfile(b_comments, bname, vbuf->comments); - if (mycomments[0][0]) - if ((fcm = fopen(b_comments, "a"))) { - fprintf(fcm, - ANSI_COLOR(36) "¡³¨Ï¥ÎªÌ" ANSI_COLOR(1;36) " %s " - ANSI_COLOR(;36) "ªº«Øij¡G" ANSI_RESET "\n", - cuser.userid); - for (i = 0; i < 3; i++) - fprintf(fcm, " %s\n", mycomments[i]); - fprintf(fcm, "\n"); - fclose(fcm); - } - } - move(b_lines - 1, 0); - outs("¤w§¹¦¨§ë²¼¡I\n"); - } - } - break; - } - free(chosen); - fclose(cfp); - pressanykey(); - return FULLUPDATE; -} - -static int -user_vote(const char *bname) -{ - int pos; - boardheader_t *fhp; - char buf[STRLEN]; - FILE *fp, *xfp; - int i, x = -1; - char genbuf[STRLEN]; - char inbuf[80]; - vote_buffer_t vbuf; - - if ((pos = getbnum(bname)) <= 0) - return 0; - - assert(0<=pos-1 && pos-1<MAX_BOARD); - fhp = bcache + pos - 1; - - move(0, 0); - clrtobot(); - - if (fhp->bvote == 0) { - vmsg("¥Ø«e¨Ã¨S¦³¥ô¦ó§ë²¼Á|¦æ¡C"); - return FULLUPDATE; - } -#if 0 // convert the filenames of first vote - convert_first_vote(fhp); -#endif - if (!HasUserPerm(PERM_LOGINOK)) { - vmsg("¹ï¤£°_! ±z¥¼º¡¤G¤Q·³, ÁÙ¨S¦³§ë²¼Åv³á!"); - return FULLUPDATE; - } - - move(0, 0); - for (i = 0; i < MAX_VOTE_NR; i++) { - snprintf(vbuf.control, sizeof(vbuf.control), "%s%d", STR_bv_control, i); - snprintf(vbuf.title, sizeof(vbuf.title), "%s%d", STR_bv_title, i); - setbfile(buf, bname, vbuf.control); - if ((fp = fopen(buf, "r"))) { - prints("(%d) ", i); - x = i; - fclose(fp); - - setbfile(buf, bname, vbuf.title); - if ((xfp = fopen(buf, "r"))) { - fgets(inbuf, sizeof(inbuf), xfp); - fclose(xfp); - } else - strlcpy(inbuf, "µL¼ÐÃD", sizeof(inbuf)); - prints("%s\n", inbuf); - } - } - - if (x < 0) - return FULLUPDATE; - - snprintf(buf, sizeof(buf), "n§ë´X¸¹§ë²¼ [%d] ", x); - - getdata(b_lines - 1, 0, buf, genbuf, 4, LCECHO); - - if (atoi(genbuf) < 0 || atoi(genbuf) > MAX_VOTE_NR) - snprintf(genbuf, sizeof(genbuf), "%d", x); - - snprintf(vbuf.control, sizeof(vbuf.control), "%s%d", STR_bv_control, atoi(genbuf)); - - setbfile(buf, bname, vbuf.control); - - if (dashf(buf)) { - return user_vote_one(&vbuf, bname, atoi(genbuf)); - } else - return FULLUPDATE; -} - -static int -vote_results(const char *bname) -{ - char buf[STRLEN]; - - setbfile(buf, bname, STR_bv_results); - if (more(buf, YEA) == -1) - vmsg("¥Ø«e¨S¦³¥ô¦ó§ë²¼ªºµ²ªG¡C"); - return FULLUPDATE; -} - -int -b_vote_maintain(void) -{ - return vote_maintain(currboard); -} - -int -b_vote(void) -{ - return user_vote(currboard); -} - -int -b_results(void) -{ - return vote_results(currboard); -} diff --git a/mbbsd/voteboard.c b/mbbsd/voteboard.c deleted file mode 100644 index 81018da2..00000000 --- a/mbbsd/voteboard.c +++ /dev/null @@ -1,400 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -#define VOTEBOARD "NewBoard" - -// user -int CheckVoteRestriction(int bid) -{ - if ((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP)) - return 1; - - // check first-login - if (cuser.firstlogin > (now - (time4_t)bcache[bid - 1].vote_limit_regtime * 2592000)) - return 0; - if (cuser.numlogins / 10 < (unsigned int)bcache[bid - 1].vote_limit_logins) - return 0; - if (cuser.numposts / 10 < (unsigned int)bcache[bid - 1].vote_limit_posts) - return 0; - if (cuser.badpost > (255 - (unsigned int)bcache[bid - 1].vote_limit_badpost)) - return 0; - - return 1; -} - -// article -int CheckVoteRestrictionFile(const fileheader_t * fhdr) -{ - if ((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP)) - return 1; - - // check first-login - if (cuser.firstlogin > (now - (time4_t)fhdr->multi.vote_limits.regtime * 2592000)) - return 0; - if (cuser.numlogins / 10 < (unsigned int)fhdr->multi.vote_limits.logins) - return 0; - if (cuser.numposts / 10 < (unsigned int)fhdr->multi.vote_limits.posts) - return 0; - if (cuser.badpost > (255 - (unsigned int)fhdr->multi.vote_limits.badpost)) - return 0; - - return 1; -} - -void -do_voteboardreply(const fileheader_t * fhdr) -{ - char genbuf[256]; - char reason[36]=""; - char fpath[80]; - char oldfpath[80]; - char opnion[10]; - char *ptr; - FILE *fo,*fi; - fileheader_t votefile; - int yes=0, no=0, len; - int fd; - unsigned long endtime=0; - - - clear(); - if (!CheckPostPerm()||HasUserPerm(PERM_NOCITIZEN)) { - move(5, 10); - vmsg("¹ï¤£°_¡A±z¥Ø«eµLªk¦b¦¹µoªí¤å³¹¡I"); - return; - } - - if (!CheckVoteRestrictionFile(fhdr)) - { - move(5, 10); // why move (5, 10)? - vmsg("§A¤£°÷¸ê²`³á¡I (¥i«ö i ¬d¬Ý¨î)"); - return; - } - setbpath(fpath, currboard); - stampfile(fpath, &votefile); - - setbpath(oldfpath, currboard); - - strcat(oldfpath, "/"); - strcat(oldfpath, fhdr->filename); - - fi = fopen(oldfpath, "r"); - assert(fi); - - while (fgets(genbuf, sizeof(genbuf), fi)) { - char *space; - - if (yes>=0) - { - if (!strncmp(genbuf, "----------",10)) - {yes=-1; continue;} - else - yes++; - } - if (yes>3) outs(genbuf); - - if (!strncmp(genbuf, "³s¸pµ²§ô®É¶¡", 12)) { - ptr = strchr(genbuf, '('); - assert(ptr); - sscanf(ptr + 1, "%lu", &endtime); - if (endtime < (unsigned long)now) { - vmsg("³s¸p®É¶¡¤w¹L"); - fclose(fi); - return; - } - } - if(yes>=0) continue; - - space = strpbrk(genbuf+4, " \n"); - if(space) *space='\0'; - if (!strncmp(genbuf + 4, cuser.userid, IDLEN)) { - move(5, 10); - outs("±z¤w¸g³s¸p¹L¥»½g¤F"); - getdata(17, 0, "nקï±z¤§«eªº³s¸p¶Ü¡H(Y/N) [N]", opnion, 3, LCECHO); - if (opnion[0] != 'y') { - fclose(fi); - return; - } - strlcpy(reason, genbuf + 19, 34); - break; - } - } - fclose(fi); - do { - if (!getdata(19, 0, "½Ð°Ý±z (Y)¤ä«ù (N)¤Ï¹ï ³oÓijÃD¡G", opnion, 3, LCECHO)) { - return; - } - } while (opnion[0] != 'y' && opnion[0] != 'n'); - sprintf(genbuf, "½Ð°Ý±z»P³oÓijÃDªºÃö«Y©Î%s²z¥Ñ¬°¦ó¡G", - opnion[0] == 'y' ? "¤ä«ù" : "¤Ï¹ï"); - if (!getdata_buf(20, 0, genbuf, reason, 35, DOECHO)) { - return; - } - if ((fd = open(oldfpath, O_RDONLY)) == -1) - return; - if(flock(fd, LOCK_EX)==-1 ) - {close(fd); return;} - if(!(fi = fopen(oldfpath, "r"))) - {flock(fd, LOCK_UN); close(fd); return;} - - if(!(fo = fopen(fpath, "w"))) - { - flock(fd, LOCK_UN); - close(fd); - fclose(fi); - return; - } - - while (fgets(genbuf, sizeof(genbuf), fi)) { - if (!strncmp("----------", genbuf, 10)) - break; - fputs(genbuf, fo); - } - if (!endtime) { - now += 14 * 24 * 60 * 60; - fprintf(fo, "³s¸pµ²§ô®É¶¡: (%d)%s\n", now, ctime4(&now)); - now -= 14 * 24 * 60 * 60; - } - fputs(genbuf, fo); - len = strlen(cuser.userid); - for(yes=0; fgets(genbuf, sizeof(genbuf), fi);) { - if (!strncmp("----------", genbuf, 10)) - break; - if (strlen(genbuf)<30 || (genbuf[4+len]==' ' && !strncmp(genbuf + 4, cuser.userid, len))) - continue; - fprintf(fo, "%3d.%s", ++yes, genbuf + 4); - } - if (opnion[0] == 'y') - fprintf(fo, "%3d.%-15s%-34s ¨Ó·½:%s\n", ++yes, cuser.userid, reason, cuser.lasthost); - fputs(genbuf, fo); - - for(no=0; fgets(genbuf, sizeof(genbuf), fi);) { - if (!strncmp("----------", genbuf, 10)) - break; - if (strlen(genbuf)<30 || (genbuf[4+len]==' ' && !strncmp(genbuf + 4, cuser.userid, len))) - continue; - fprintf(fo, "%3d.%s", ++no, genbuf + 4); - } - if (opnion[0] == 'n') - fprintf(fo, "%3d.%-15s%-34s ¨Ó·½:%s\n", ++no, cuser.userid, reason, cuser.lasthost); - fprintf(fo, "----------Á`p----------\n"); - fprintf(fo, "¤ä«ù¤H¼Æ:%-9d¤Ï¹ï¤H¼Æ:%-9d\n", yes, no); - fprintf(fo, "\n--\n¡° µo«H¯¸ :" BBSNAME "(" MYHOSTNAME - ") \n¡» From: ³s¸p¤å³¹\n"); - - flock(fd, LOCK_UN); - close(fd); - fclose(fi); - fclose(fo); - unlink(oldfpath); - rename(fpath, oldfpath); -} - -int -do_voteboard(int type) -{ - fileheader_t votefile; - char topic[100]; - char title[80]; - char genbuf[1024]; - char fpath[80]; - FILE *fp; - int temp; - - clear(); - if (!CheckPostPerm()) { - move(5, 10); - vmsg("¹ï¤£°_¡A±z¥Ø«eµLªk¦b¦¹µoªí¤å³¹¡I"); - return FULLUPDATE; - } - if (!CheckVoteRestriction(currbid)) - { - move(5, 10); // why move (5, 10)? - vmsg("§A¤£°÷¸ê²`³á¡I (¥i«ö i ¬d¬Ý¨î)"); - return FULLUPDATE; - } - move(0, 0); - clrtobot(); - outs("±z¥¿¦b¨Ï¥Î" BBSNAME "ªº³s¸p¨t²Î\n"); - outs("¥»³s¸p¨t²Î±N¸ß°Ý±z¤@¨Ç°ÝÃD¡A½Ð¤p¤ß¦^µª¤~¯à¶}©l³s¸p\n"); - outs("¥ô·N´£¥X³s¸p®×ªÌ¡A±N³Q¦C¤J¤£¨üÅwªï¨Ï¥ÎªÌ³á\n"); - move(4, 0); - clrtobot(); - outs("(1)¬¡°Ê³s¸p (2)°O¦W¤½§ë "); - if(type==0) - outs("(3)¥Ó½Ð·sªO (4)¼o°£ÂªO (5)³s¸pªO¥D \n(6)½}§KªO¥D (7)³s¸p¤p²Õªø (8)½}§K¤p²Õªø (9)¥Ó½Ð·s¸s²Õ\n"); - - do { - getdata(6, 0, "½Ð¿é¤J³s¸pÃþ§O [0:¨ú®ø]¡G", topic, 3, DOECHO); - temp = atoi(topic); - } while (temp < 0 || temp > 9 || (type && temp>2)); - switch (temp) { - case 0: - return FULLUPDATE; - case 1: - if (!getdata(7, 0, "½Ð¿é¤J¬¡°Ê¥DÃD¡G", topic, 30, DOECHO)) - return FULLUPDATE; - snprintf(title, sizeof(title), "%s %s", "[¬¡°Ê³s¸p]", topic); - snprintf(genbuf, sizeof(genbuf), - "%s\n\n%s%s\n", "¬¡°Ê³s¸p", "¬¡°Ê¥DÃD: ", topic); - strcat(genbuf, "\n¬¡°Ê¤º®e: \n"); - break; - case 2: - if (!getdata(7, 0, "½Ð¿é¤J¤½§ë¥DÃD¡G", topic, 30, DOECHO)) - return FULLUPDATE; - snprintf(title, sizeof(title), "%s %s", "[°O¦W¤½§ë]", topic); - snprintf(genbuf, sizeof(genbuf), - "%s\n\n%s%s\n", "°O¦W¤½§ë", "¤½§ë¥DÃD: ", topic); - strcat(genbuf, "\n¤½§ëì¦]: \n"); - break; - case 3: - do { - if (!getdata(7, 0, "½Ð¿é¤J¬ÝªO^¤å¦WºÙ¡G", topic, IDLEN + 1, DOECHO)) - return FULLUPDATE; - else if (invalid_brdname(topic)) - outs("¤£¬O¥¿½Tªº¬ÝªO¦WºÙ"); - else if (getbnum(topic) > 0) - outs("¥»¦WºÙ¤w¸g¦s¦b"); - else - break; - } while (temp > 0); - snprintf(title, sizeof(title), "[¥Ó½Ð·sªO] %s", topic); - snprintf(genbuf, sizeof(genbuf), - "%s\n\n%s%s\n%s", "¥Ó½Ð·sªO", "^¤å¦WºÙ: ", topic, "¤¤¤å¦WºÙ: "); - - if (!getdata(8, 0, "½Ð¿é¤J¬ÝªO¤¤¤å¦WºÙ¡G", topic, BTLEN + 1, DOECHO)) - return FULLUPDATE; - strcat(genbuf, topic); - strcat(genbuf, "\n¬ÝªOÃþ§O: "); - if (!getdata(9, 0, "½Ð¿é¤J¬ÝªOÃþ§O¡G", topic, 20, DOECHO)) - return FULLUPDATE; - strcat(genbuf, topic); - strcat(genbuf, "\nªO¥D¦W³æ: "); - getdata(10, 0, "½Ð¿é¤JªO¥D¦W³æ¡G", topic, IDLEN * 3 + 3, DOECHO); - strcat(genbuf, topic); - strcat(genbuf, "\n¥Ó½Ðì¦]: \n"); - break; - case 4: - move(1,0); clrtobot(); - generalnamecomplete("½Ð¿é¤J¬ÝªO^¤å¦WºÙ¡G", - topic, IDLEN+1, - SHM->Bnumber, - &completeboard_compar, - &completeboard_permission, - &completeboard_getname); - snprintf(title, sizeof(title), "[¼o°£ÂªO] %s", topic); - snprintf(genbuf, sizeof(genbuf), - "%s\n\n%s%s\n", "¼o°£ÂªO", "^¤å¦WºÙ: ", topic); - strcat(genbuf, "\n¼o°£ì¦]: \n"); - break; - case 5: - move(1,0); clrtobot(); - generalnamecomplete("½Ð¿é¤J¬ÝªO^¤å¦WºÙ¡G", - topic, IDLEN+1, - SHM->Bnumber, - &completeboard_compar, - &completeboard_permission, - &completeboard_getname); - snprintf(title, sizeof(title), "[³s¸pªO¥D] %s", topic); - snprintf(genbuf, sizeof(genbuf), "%s\n\n%s%s\n%s%s", "³s¸pªO¥D", "^¤å¦WºÙ: ", topic, "¥Ó½Ð ID : ", cuser.userid); - strcat(genbuf, "\n¥Ó½Ð¬F¨£: \n"); - break; - case 6: - move(1,0); clrtobot(); - generalnamecomplete("½Ð¿é¤J¬ÝªO^¤å¦WºÙ¡G", - topic, IDLEN+1, - SHM->Bnumber, - &completeboard_compar, - &completeboard_permission, - &completeboard_getname); - snprintf(title, sizeof(title), "[½}§KªO¥D] %s", topic); - snprintf(genbuf, sizeof(genbuf), - "%s\n\n%s%s\n%s", "½}§KªO¥D", "^¤å¦WºÙ: ", - topic, "ªO¥D ID : "); - temp=getbnum(topic); - assert(0<=temp-1 && temp-1<MAX_BOARD); - do { - if (!getdata(7, 0, "½Ð¿é¤JªO¥DID¡G", topic, IDLEN + 1, DOECHO)) - return FULLUPDATE; - }while (!userid_is_BM(topic, bcache[temp - 1].BM)); - strcat(genbuf, topic); - strcat(genbuf, "\n½}§Kì¦]: \n"); - break; - case 7: - if (!getdata(7, 0, "½Ð¿é¤J¤p²Õ¤¤^¤å¦WºÙ¡G", topic, 30, DOECHO)) - return FULLUPDATE; - snprintf(title, sizeof(title), "[³s¸p¤p²Õªø] %s", topic); - snprintf(genbuf, sizeof(genbuf), - "%s\n\n%s%s\n%s%s", "³s¸p¤p²Õªø", "¤p²Õ¦WºÙ: ", - topic, "¥Ó½Ð ID : ", cuser.userid); - strcat(genbuf, "\n¥Ó½Ð¬F¨£: \n"); - break; - case 8: - if (!getdata(7, 0, "½Ð¿é¤J¤p²Õ¤¤^¤å¦WºÙ¡G", topic, 30, DOECHO)) - return FULLUPDATE; - snprintf(title, sizeof(title), "[½}§K¤p²Õªø] %s", topic); - snprintf(genbuf, sizeof(genbuf), "%s\n\n%s%s\n%s", - "½}§K¤p²Õªø", "¤p²Õ¦WºÙ: ", topic, "¤p²Õªø ID : "); - if (!getdata(8, 0, "½Ð¿é¤J¤p²ÕªøID¡G", topic, IDLEN + 1, DOECHO)) - return FULLUPDATE; - strcat(genbuf, topic); - strcat(genbuf, "\n½}§Kì¦]: \n"); - break; - case 9: - if (!getdata(7, 0, "½Ð¿é¤J¸s²Õ¤¤^¤å¦WºÙ¡G", topic, 30, DOECHO)) - return FULLUPDATE; - snprintf(title, sizeof(title), "[¥Ó½Ð·s¸s²Õ] %s", topic); - snprintf(genbuf, sizeof(genbuf), "%s\n\n%s%s\n%s%s", - "¥Ó½Ð¸s²Õ", "¸s²Õ¦WºÙ: ", topic, "¥Ó½Ð ID : ", cuser.userid); - strcat(genbuf, "\n¥Ó½Ð¬F¨£: \n"); - break; - default: - return FULLUPDATE; - } - outs("½Ð¿é¤J²¤¶©Î¬F¨£(¦Ü¦h¤¦æ)¡An²M·¡¶ñ¼g"); - for (temp = 12; temp < 17; temp++) { - if (!getdata(temp, 0, "¡G", topic, 60, DOECHO)) - break; - strcat(genbuf, topic); - strcat(genbuf, "\n"); - } - if (temp == 11) - return FULLUPDATE; - strcat(genbuf, "³s¸pµ²§ô®É¶¡: "); - now += 14 * 24 * 60 * 60; - snprintf(topic, sizeof(topic), "(%d)", now); - strcat(genbuf, topic); - strcat(genbuf, ctime4(&now)); - strcat(genbuf, "\n"); - now -= 14 * 24 * 60 * 60; - strcat(genbuf, "----------¤ä«ù----------\n"); - strcat(genbuf, "----------¤Ï¹ï----------\n"); - outs("¶}©l³s¸p¹Æ"); - setbpath(fpath, currboard); - stampfile(fpath, &votefile); - - if (!(fp = fopen(fpath, "w"))) { - outs("¶}ÀÉ¥¢±Ñ¡A½ÐµyÔ«¨Ó¤@¦¸"); - return FULLUPDATE; - } - fprintf(fp, "%s%s %s%s\n%s%s\n%s%s\n", "§@ªÌ: ", cuser.userid, - "¬ÝªO: ", currboard, - "¼ÐÃD: ", title, - "®É¶¡: ", ctime4(&now)); - fprintf(fp, "%s\n", genbuf); - fclose(fp); - strlcpy(votefile.owner, cuser.userid, sizeof(votefile.owner)); - strlcpy(votefile.title, title, sizeof(votefile.title)); - votefile.filemode |= FILE_VOTE; - /* use lower 16 bits of 'money' to store limits */ - /* lower 8 bits are posts, higher 8 bits are logins */ - votefile.multi.vote_limits.regtime = bcache[currbid - 1].vote_limit_regtime; - votefile.multi.vote_limits.logins = bcache[currbid - 1].vote_limit_logins; - votefile.multi.vote_limits.posts = bcache[currbid - 1].vote_limit_posts; - votefile.multi.vote_limits.badpost = bcache[currbid - 1].vote_limit_badpost; - setbdir(genbuf, currboard); - if (append_record(genbuf, &votefile, sizeof(votefile)) != -1) - setbtotal(currbid); - do_voteboardreply(&votefile); - return FULLUPDATE; -} diff --git a/mbbsd/xyz.c b/mbbsd/xyz.c deleted file mode 100644 index fd7d5f4e..00000000 --- a/mbbsd/xyz.c +++ /dev/null @@ -1,338 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -int -x_boardman(void) -{ - more("etc/topboardman", YEA); - return 0; -} - -int -x_user100(void) -{ - more("etc/topusr100", YEA); - return 0; -} - -int -x_history(void) -{ - more("etc/history", YEA); - return 0; -} - -#ifdef HAVE_X_BOARDS -static int -x_boards(void) -{ - more("etc/topboard.tmp", YEA); - return 0; -} -#endif - -int -x_birth(void) -{ - more("etc/birth.today", YEA); - return 0; -} - -int -x_weather(void) -{ - more("etc/weather.tmp", YEA); - return 0; -} - -int -x_mrtmap(void) -{ - more("etc/MRT.map", YEA); - return 0; -} - -int -x_stock(void) -{ - more("etc/stock.tmp", YEA); - return 0; -} - -int -x_note(void) -{ - more(fn_note_ans, YEA); - return 0; -} - -int -x_issue(void) -{ - more("etc/day", YEA); - return 0; -} - -int -x_week(void) -{ - more("etc/week", YEA); - return 0; -} - -int -x_today(void) -{ - more("etc/today", YEA); - return 0; -} - -int -x_yesterday(void) -{ - more("etc/yesterday", YEA); - return 0; -} - -int -x_login(void) -{ - more("etc/Welcome_login.0", YEA); - return 0; -} - -#ifdef HAVE_INFO -static int -x_program(void) -{ - more("etc/version", YEA); - return 0; -} -#endif - -#ifdef HAVE_LICENSE -static int -x_gpl(void) -{ - more("etc/GPL", YEA); - return 0; -} -#endif - -int -note(void) -{ - char *fn_note_tmp = "note.tmp"; - char *fn_note_dat = "note.dat"; - int total = 0, i, collect, len; - struct stat st; - char buf[256], buf2[80]; - int fd, fx; - FILE *fp, *foo; - - typedef struct notedata_t { - time4_t date; - char userid[IDLEN + 1]; - char nickname[19]; - char buf[3][80]; - } notedata_t; - notedata_t myitem; - - if (cuser.money < 5) { - vmsg(ANSI_COLOR(1;41) " «u§r! n§ë¤»È¤~¯à¯d¨¥...¨S¿úC.." ANSI_RESET); - return 0; - } - setutmpmode(EDNOTE); - do { - myitem.buf[0][0] = myitem.buf[1][0] = myitem.buf[2][0] = '\0'; - move(12, 0); - clrtobot(); - outs("\n§ë¤»È... ¹Í... ½Ð¯d¨¥ (¦Ü¦h¤T¦æ)¡A«ö[Enter]µ²§ô"); - for (i = 0; (i < 3) && getdata(16 + i, 0, "¡G", myitem.buf[i], - sizeof(myitem.buf[i]) - 5, DOECHO) - && *myitem.buf[i]; i++); - getdata(b_lines - 1, 0, "(S)Àx¦s (E)«·s¨Ó¹L (Q)¨ú®ø¡H[S] ", - buf, 3, LCECHO); - - if (buf[0] == 'q' || (i == 0 && *buf != 'e')) - return 0; - } while (buf[0] == 'e'); - demoney(-5); - strcpy(myitem.userid, cuser.userid); - strlcpy(myitem.nickname, cuser.nickname, sizeof(myitem.nickname)); - myitem.date = now; - - /* begin load file */ - if ((foo = fopen(".note", "a")) == NULL) - return 0; - - unlink(fn_note_ans); // remove first to prevent mmap(pmore) crash - if ((fp = fopen(fn_note_ans, "w")) == NULL) { - fclose(fp); - return 0; - } - - if ((fx = open(fn_note_tmp, O_WRONLY | O_CREAT, 0644)) <= 0) { - fclose(foo); - fclose(fp); - return 0; - } - - if ((fd = open(fn_note_dat, O_RDONLY)) == -1) - total = 1; - else if (fstat(fd, &st) != -1) { - total = st.st_size / sizeof(notedata_t) + 1; - if (total > MAX_NOTE) - total = MAX_NOTE; - } - fputs(ANSI_COLOR(1;31;44) "¡ó¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢t" - ANSI_COLOR(37) "»Ä²¢W»¶ªO" ANSI_COLOR(31) "¢u¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢s¡ó" - ANSI_RESET "\n", fp); - collect = 1; - - while (total) { - snprintf(buf, sizeof(buf), ANSI_COLOR(1;31) "ùÝ¢t" ANSI_COLOR(32) " %s " ANSI_COLOR(37) "(%s)", - myitem.userid, myitem.nickname); - len = strlen(buf); - - for (i = len; i < 71; i++) - strcat(buf, " "); - snprintf(buf2, sizeof(buf2), " " ANSI_COLOR(1;36) "%.16s" ANSI_COLOR(31) " ¢uùß" ANSI_RESET "\n", - Cdate(&(myitem.date))); - strcat(buf, buf2); - fputs(buf, fp); - if (collect) - fputs(buf, foo); - for (i = 0; i < 3 && *myitem.buf[i]; i++) { - fprintf(fp, ANSI_COLOR(1;31) "¢x" ANSI_RESET "%-74.74s" ANSI_COLOR(1;31) "¢x" ANSI_RESET "\n", - myitem.buf[i]); - if (collect) - fprintf(foo, ANSI_COLOR(1;31) "¢x" ANSI_RESET "%-74.74s" ANSI_COLOR(1;31) "¢x" ANSI_RESET "\n", - myitem.buf[i]); - } - fputs(ANSI_COLOR(1;31) "ùã¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" - "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢sùå" ANSI_RESET "\n", fp); - - if (collect) { - fputs(ANSI_COLOR(1;31) "ùã¢s¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" - "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢sùå" ANSI_RESET "\n", foo); - fclose(foo); - collect = 0; - } - write(fx, &myitem, sizeof(myitem)); - - if (--total) - read(fd, (char *)&myitem, sizeof(myitem)); - } - fputs(ANSI_COLOR(1;31;44) "¡ó¢r¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w" - "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢r¡ó" ANSI_RESET "\n", fp); - fclose(fp); - close(fd); - close(fx); - Rename(fn_note_tmp, fn_note_dat); - more(fn_note_ans, YEA); - return 0; -} - -static void -mail_sysop(void) -{ - FILE *fp; - char genbuf[200]; - - if ((fp = fopen("etc/sysop", "r"))) { - int i, j; - char *ptr; - - typedef struct sysoplist_t { - char userid[IDLEN + 1]; - char duty[40]; - } sysoplist_t; - sysoplist_t sysoplist[9]; - - j = 0; - while (fgets(genbuf, 128, fp)) { - if ((ptr = strchr(genbuf, '\n'))) { - *ptr = '\0'; - if ((ptr = strchr(genbuf, ':'))) { - *ptr = '\0'; - do { - i = *++ptr; - } while (i == ' ' || i == '\t'); - if (i) { - strcpy(sysoplist[j].userid, genbuf); - strcpy(sysoplist[j++].duty, ptr); - } - } - } - } - fclose(fp); - - move(12, 0); - clrtobot(); - outs(" ½s¸¹ ¯¸ªø ID Åv³d¹º¤À\n\n"); - - for (i = 0; i < j; i++) - prints("%15d. " ANSI_COLOR(1;%d) "%-16s%s" ANSI_COLOR(0) "\n", - i + 1, 31 + i % 7, sysoplist[i].userid, sysoplist[i].duty); - prints("%-14s0. " ANSI_COLOR(1;%d) "Â÷¶}" ANSI_COLOR(0) "", "", 31 + j % 7); - getdata(b_lines - 1, 0, " ½Ð¿é¤J¥N½X[0]¡G", - genbuf, 4, DOECHO); - i = genbuf[0] - '0' - 1; - if (i >= 0 && i < j) { - char *suser = sysoplist[i].userid; - clear(); - showplans(suser); - do_send(suser, NULL); - } - } -} - -int -m_sysop(void) -{ - setutmpmode(MSYSOP); - mail_sysop(); - return 0; -} - -int -Goodbye(void) -{ - char genbuf[100]; - - getdata(b_lines - 1, 0, "±z½T©wnÂ÷¶}¡i " BBSNAME " ¡j¶Ü(Y/N)¡H[N] ", - genbuf, 3, LCECHO); - - if (*genbuf != 'y') - return 0; - - movie(999999); - if (cuser.userlevel) { - getdata(b_lines - 1, 0, - "(G)ÀH·¦Ó³u (M)¦«¹Ú¯¸ªø (N)»Ä²¢W»¶¬y¨¥ªO¡H[G] ", - genbuf, 3, LCECHO); - if (genbuf[0] == 'm') - mail_sysop(); - else if (genbuf[0] == 'n') - note(); - } - clear(); - - - more("etc/Logout", NA); - - { - int diff = (now - login_start_time) / 60; - sprintf(genbuf, "¦¹¦¸°±¯d®É¶¡: %d ¤p®É %2d ¤À", - diff / 60, diff % 60); - } - if(!(cuser.userlevel & PERM_LOGINOK)) - vmsg("©|¥¼§¹¦¨µù¥U¡C¦pn´£ª@Åv½Ð°Ñ¦Ò¥»¯¸¤½§GÄæ¿ì²zµù¥U"); - else - vmsg(genbuf); - // pressanykey(); - - u_exit("EXIT "); - return QUIT; -} |