From ae31e19f92e717919ac8e3db9039eb38d2b89aae Mon Sep 17 00:00:00 2001 From: in2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> Date: Thu, 7 Mar 2002 15:13:44 +0000 Subject: Initial revision git-svn-id: http://opensvn.csie.org/pttbbs/pttbbs/trunk/pttbbs@1 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- mbbsd/.cvsignore | 2 + mbbsd/Makefile | 45 + mbbsd/admin.c | 1105 ++++++++++++++++++++++ mbbsd/announce.c | 1590 ++++++++++++++++++++++++++++++++ mbbsd/args.c | 62 ++ mbbsd/bbcall.c | 268 ++++++ mbbsd/bbs.c | 1904 ++++++++++++++++++++++++++++++++++++++ mbbsd/board.c | 1098 ++++++++++++++++++++++ mbbsd/cache.c | 1053 +++++++++++++++++++++ mbbsd/cal.c | 512 ++++++++++ mbbsd/calendar.c | 284 ++++++ mbbsd/card.c | 625 +++++++++++++ mbbsd/chat.c | 623 +++++++++++++ mbbsd/chc_draw.c | 187 ++++ mbbsd/chc_net.c | 28 + mbbsd/chc_play.c | 277 ++++++ mbbsd/chc_rule.c | 186 ++++ mbbsd/chicken.c | 989 ++++++++++++++++++++ mbbsd/dark.c | 456 +++++++++ mbbsd/descrypt.c | 616 +++++++++++++ mbbsd/dice.c | 447 +++++++++ mbbsd/edit.c | 2256 +++++++++++++++++++++++++++++++++++++++++++++ mbbsd/friend.c | 509 ++++++++++ mbbsd/gamble.c | 361 ++++++++ mbbsd/gomo.c | 417 +++++++++ mbbsd/gomo1.c | 136 +++ mbbsd/guess.c | 364 ++++++++ mbbsd/indict.c | 184 ++++ mbbsd/io.c | 611 ++++++++++++ mbbsd/kaede.c | 95 ++ mbbsd/lovepaper.c | 120 +++ mbbsd/mail.c | 1675 +++++++++++++++++++++++++++++++++ mbbsd/mbbsd.c | 1465 +++++++++++++++++++++++++++++ mbbsd/menu.c | 596 ++++++++++++ mbbsd/more.c | 931 +++++++++++++++++++ mbbsd/name.c | 473 ++++++++++ mbbsd/osdep.c | 79 ++ mbbsd/othello.c | 541 +++++++++++ mbbsd/page.c | 130 +++ mbbsd/passwd.c | 138 +++ mbbsd/read.c | 998 ++++++++++++++++++++ mbbsd/record.c | 536 +++++++++++ mbbsd/register.c | 339 +++++++ mbbsd/screen.c | 559 +++++++++++ mbbsd/stuff.c | 524 +++++++++++ mbbsd/syspost.c | 102 ++ mbbsd/talk.c | 2663 +++++++++++++++++++++++++++++++++++++++++++++++++++++ mbbsd/term.c | 144 +++ mbbsd/toolkit.c | 14 + mbbsd/topsong.c | 79 ++ mbbsd/uptime | 23 + mbbsd/user.c | 980 ++++++++++++++++++++ mbbsd/var.c | 268 ++++++ mbbsd/vice.c | 151 +++ mbbsd/vote.c | 1068 +++++++++++++++++++++ mbbsd/voteboard.c | 447 +++++++++ mbbsd/xyz.c | 448 +++++++++ 57 files changed, 32781 insertions(+) create mode 100644 mbbsd/.cvsignore create mode 100644 mbbsd/Makefile create mode 100644 mbbsd/admin.c create mode 100644 mbbsd/announce.c create mode 100644 mbbsd/args.c create mode 100644 mbbsd/bbcall.c create mode 100644 mbbsd/bbs.c create mode 100644 mbbsd/board.c create mode 100644 mbbsd/cache.c create mode 100644 mbbsd/cal.c create mode 100644 mbbsd/calendar.c create mode 100644 mbbsd/card.c create mode 100644 mbbsd/chat.c create mode 100644 mbbsd/chc_draw.c create mode 100644 mbbsd/chc_net.c create mode 100644 mbbsd/chc_play.c create mode 100644 mbbsd/chc_rule.c create mode 100644 mbbsd/chicken.c create mode 100644 mbbsd/dark.c create mode 100644 mbbsd/descrypt.c create mode 100644 mbbsd/dice.c create mode 100644 mbbsd/edit.c create mode 100644 mbbsd/friend.c create mode 100644 mbbsd/gamble.c create mode 100644 mbbsd/gomo.c create mode 100644 mbbsd/gomo1.c create mode 100644 mbbsd/guess.c create mode 100644 mbbsd/indict.c create mode 100644 mbbsd/io.c create mode 100644 mbbsd/kaede.c create mode 100644 mbbsd/lovepaper.c create mode 100644 mbbsd/mail.c create mode 100644 mbbsd/mbbsd.c create mode 100644 mbbsd/menu.c create mode 100644 mbbsd/more.c create mode 100644 mbbsd/name.c create mode 100644 mbbsd/osdep.c create mode 100644 mbbsd/othello.c create mode 100644 mbbsd/page.c create mode 100644 mbbsd/passwd.c create mode 100644 mbbsd/read.c create mode 100644 mbbsd/record.c create mode 100644 mbbsd/register.c create mode 100644 mbbsd/screen.c create mode 100644 mbbsd/stuff.c create mode 100644 mbbsd/syspost.c create mode 100644 mbbsd/talk.c create mode 100644 mbbsd/term.c create mode 100644 mbbsd/toolkit.c create mode 100644 mbbsd/topsong.c create mode 100644 mbbsd/uptime create mode 100644 mbbsd/user.c create mode 100644 mbbsd/var.c create mode 100644 mbbsd/vice.c create mode 100644 mbbsd/vote.c create mode 100644 mbbsd/voteboard.c create mode 100644 mbbsd/xyz.c (limited to 'mbbsd') diff --git a/mbbsd/.cvsignore b/mbbsd/.cvsignore new file mode 100644 index 00000000..35f9f2d1 --- /dev/null +++ b/mbbsd/.cvsignore @@ -0,0 +1,2 @@ +*.o +mbbsd diff --git a/mbbsd/Makefile b/mbbsd/Makefile new file mode 100644 index 00000000..886944f3 --- /dev/null +++ b/mbbsd/Makefile @@ -0,0 +1,45 @@ +# $Id: Makefile,v 1.1 2002/03/07 15:13:48 in2 Exp $ + +BBSHOME?=$(HOME) +OSTYPE=FreeBSD + +# FreeBSD +CFLAGS_FreeBSD= -pipe -Wall -g -O3 -DHAVE_SETPROCTITLE -DBBSHOME='"$(BBSHOME)"' -DFreeBSD -I../include +LDFLAGS_FreeBSD=-pipe -Wall -g -O3 +LIBS_FreeBSD= -lutil -lkvm + +# Linux +CFLAGS_linux= -pipe -Wall -g -O3 -DHAVE_DES_CRYPT -DBBSHOME='"$(BBSHOME)"' -DLinux -I../include -s +LDFLAGS_linux= -pipe -Wall -g -O3 +LIBS_linux= -lcrypt + +CFLAGS= $(CFLAGS_$(OSTYPE)) +LDFLAGS=$(LDFLAGS_$(OSTYPE)) +LIBS= $(LIBS_$(OSTYPE)) + +CC= gcc +PROG= mbbsd +OBJS= admin.o announce.o args.o bbcall.o bbs.o board.o cache.o cal.o card.o\ + chat.o chc_draw.o chc_net.o chc_play.o chc_rule.o chicken.o dark.o\ + dice.o edit.o friend.o gamble.o gomo.o gomo1.o guess.o indict.o io.o\ + kaede.o lovepaper.o mail.o mbbsd.o menu.o more.o name.o osdep.o\ + othello.o page.o read.o record.o register.o screen.o stuff.o\ + talk.o term.o topsong.o user.o vice.o vote.o xyz.o\ + voteboard.o syspost.o var.o descrypt.o toolkit.o passwd.o\ + calendar.o + +.SUFFIXES: .c .o +.c.o: + $(CC) $(CFLAGS) -c $*.c + +all: $(PROG) + +$(PROG): $(OBJS) + $(CC) $(LDFLAGS) -o $(PROG) $(OBJS) $(LIBS) + +install: $(PROG) + install -d $(BBSHOME)/bin/ + install -c -m 755 $(PROG) $(BBSHOME)/bin/ + +clean: + rm -f $(OBJS) $(PROG) diff --git a/mbbsd/admin.c b/mbbsd/admin.c new file mode 100644 index 00000000..14bc9721 --- /dev/null +++ b/mbbsd/admin.c @@ -0,0 +1,1105 @@ +/* $Id: admin.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +extern char *msg_uid; +extern userec_t xuser; +extern char *err_uid; +extern boardheader_t *bcache; + +/* �ϥΪ̺z */ +int m_user() { + userec_t muser; + int id; + char genbuf[200]; + + stand_title("�ϥΪ̳]�w"); + usercomplete(msg_uid, genbuf); + if(*genbuf) { + move(2, 0); + if((id = getuser(genbuf))) { + memcpy(&muser, &xuser, sizeof(muser)); + user_display(&muser, 1); + uinfo_query(&muser, 1, id); + } else { + outs(err_uid); + clrtoeol(); + pressanykey(); + } + } + return 0; +} + +extern int b_lines; + +static int search_key_user(char *passwdfile, int mode) { + userec_t user; + int ch; + int coun = 0; + FILE *fp1 = fopen(passwdfile, "r"); + char buf[128], key[22], genbuf[8]; + + clear(); + getdata(0, 0, mode ? "�п�J�ϥΪ�����r[�q��|�a�}|�m�W|�W���a�I|" + "email|�p��id] :" : "�п�Jid :", key, 21, DOECHO); + while((fread(&user, sizeof(user), 1, fp1)) > 0 && coun < MAX_USERS) { + if(!(++coun & 15)) { + move(1, 0); + sprintf(buf, "�� [%d] �����\n", coun); + outs(buf); + refresh(); + } + if(!strcasecmp(user.userid, key) || + (mode && ( + strstr(user.realname, key) || strstr(user.username, key) || + strstr(user.lasthost, key) || strstr(user.email, key) || + strstr(user.address, key) || strstr(user.justify, key) || + strstr(user.mychicken.name, key)))) { + move(1, 0); + sprintf(buf, "�� [%d] �����\n", coun); + outs(buf); + refresh(); + + user_display(&user, 1); + uinfo_query(&user, 1, coun); + outs("\033[44m �ť���\033[37m:�j�M�U�@��" + " \033[33m Q\033[37m: ���}"); + outs(mode ? " \033[m " : + " S: ���γƥ���� \033[m "); + while(1) { + while((ch = igetch()) == 0); + if(ch == ' ') + break; + if(ch == 'q' || ch == 'Q') + return 0; + if(ch == 's' && !mode) { + if((ch = searchuser(user.userid))) { + setumoney(ch,user.money); + passwd_update(ch, &user); + return 0; + } else { + move(b_lines - 1, 0); + genbuf[0] = 'n'; + getdata(0, 0, + "�ثe�� PASSWD �ɨS���� ID�A�s�W�ܡH[y/N]", + genbuf, 3, LCECHO); + if(genbuf[0] == 'n') { + outs("�ثe��PASSWDS�ɨS����id " + "�Х�new�@�ӳo��id���b��"); + } else { + int allocid = getnewuserid(); + + if(allocid > MAX_USERS || allocid <= 0) { + fprintf(stderr, "�����H�f�w�F���M�I\n"); + exit(1); + } + + if(passwd_update(allocid, &user) == -1) { + fprintf(stderr, "�Ⱥ��F�A�A���I\n"); + exit(1); + } + setuserid(allocid, user.userid); + if(!searchuser(user.userid)) { + fprintf(stderr, "�L�k�إ߱b��\n"); + exit(1); + } + return 0; + } + } + } + } + } + } + + fclose(fp1); + return 0; +} + +/* �H���N key �M��ϥΪ� */ +int search_user_bypwd() { + search_key_user(FN_PASSWD, 1); + return 0; +} + +/* �M��ƥ����ϥΪ̸�� */ +int search_user_bybakpwd() { + char *choice[] = { + "PASSWDS.NEW1", "PASSWDS.NEW2", "PASSWDS.NEW3", + "PASSWDS.NEW4", "PASSWDS.NEW5", "PASSWDS.NEW6", + "PASSWDS.BAK" + }; + int ch; + + clear(); + move(1, 1); + outs("�п�J�A�n�ΨӴM��ƥ����ɮ� �Ϋ� 'q' ���}\n"); + outs(" [\033[1;31m1\033[m]�@�ѫe, [\033[1;31m2\033[m]��ѫe, " + "[\033[1;31m3\033[m]�T�ѫe\n"); + outs(" [\033[1;31m4\033[m]�|�ѫe, [\033[1;31m5\033[m]���ѫe, " + "[\033[1;31m6\033[m]���ѫe\n"); + outs(" [7]�ƥ���\n"); + do { + move(5, 1); + outs("��� => "); + ch = igetch(); + if(ch == 'q' || ch == 'Q') + return 0; + } while (ch < '1' || ch > '8'); + ch -= '1'; + search_key_user(choice[ch], 0); + return 0; +} + +static void bperm_msg(boardheader_t *board) { + prints("\n�]�w [%s] �ݪO��(%s)�v���G", board->brdname, + board->brdattr & BRD_POSTMASK ? "�o��" : "�\\Ū"); +} + +extern char* str_permboard[]; + +unsigned int setperms(unsigned int pbits, char *pstring[]) { + register int i; + char choice[4]; + + 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(getdata(b_lines - 1, 0, "�Ы� [A-5] �����]�w�A�� [Return] �����G", + choice, 3, LCECHO)) { + i = choice[0] - 'a'; + if(i < 0) + i = choice[0] - '0' + 26; + if(i >= NUMPERMS) + bell(); + else { + pbits ^= (1 << i); + move(i % 16 + 4, i <= 15 ? 24 : 64); + prints((pbits >> i) & 1 ? "��" : "��"); + } + } + return pbits; +} + +/* �۰ʳ]�ߺ�ذ� */ +void setup_man(boardheader_t * board) { + char genbuf[200]; + + setapath(genbuf, board->brdname); + mkdir(genbuf, 0755); +} + +extern char *fn_board; +extern char *err_bid; +extern userec_t cuser; +extern char *msg_sure_ny; +extern char* str_permid[]; + +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) { + outs(err_bid); + pressanykey(); + return -1; + } + + 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); + sprintf(genbuf, "�ݪO (E)�]�w (V)�H�k/�Ѱ� %s (D)�R�� [Q]�����H", + HAS_PERM(PERM_SYSOP) ? + " (B)BVote (S)�Ϧ^�峹" : ""); + getdata(10, 0, genbuf, ans, 3, LCECHO); + + switch(*ans) { + case 's': + if(HAS_PERM(PERM_SYSOP) ) { + char actionbuf[512]; + + sprintf(actionbuf, BBSHOME "/bin/buildir boards/%s &", + bh.brdname); + system(actionbuf); + } + break; + case 'b': + if(HAS_PERM(PERM_SYSOP)) { + char bvotebuf[10]; + + memcpy(&newbh, &bh, sizeof(bh)); + sprintf(bvotebuf, "%d", newbh.bvote); + move(20, 0); + prints("�ݪ� %s ��Ӫ� BVote�G%d", bh.brdname, bh.bvote); + getdata_str(21, 0, "�s�� Bvote�G", genbuf, 5, LCECHO, bvotebuf); + newbh.bvote = atoi(genbuf); + 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("�ݪ��ث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; + substitute_record(fn_board, &newbh, sizeof(newbh), bid); + reset_board(bid); + log_usies("ViolateLawSet", newbh.brdname); + } + break; + case 'd': + getdata_str(9, 0, msg_sure_ny, genbuf, 3, LCECHO, "N"); + if(genbuf[0] != 'y' || !bname[0]) + outs(MSG_DEL_CANCEL); + else { + strcpy(bname, bh.brdname); + sprintf(genbuf, + "/bin/tar zcvf tmp/board_%s.tgz boards/%s man/%s >/dev/null 2>&1;" + "/bin/rm -fr boards/%s man/%s", + bname, bname, bname, bname, bname); + system(genbuf); + memset(&bh, 0, sizeof(bh)); + sprintf(bh.title, "%s �ݪO %s �R��", bname, cuser.userid); + post_msg("Security", bh.title,"�Ъ`�N�R�����X�k��","[�t�Φw����]"); + substitute_record(fn_board, &bh, sizeof(bh), bid); + reset_board(bid); + log_usies("DelBoard", bh.title); + outs("�R�O����"); + } + break; + case 'e': + 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)) { + strcpy(newbh.brdname, genbuf); + break; + } + } + + do { + getdata_str(12, 0, "�ݪO���O�G", genbuf, 5, DOECHO, bh.title); + if(strlen(genbuf) == 4) + break; + } while (1); + + if(strlen(genbuf) >= 4) + strncpy(newbh.title, genbuf, 4); + + newbh.title[4] = ' '; + + getdata_str(14, 0, "�ݪO�D�D�G", genbuf, BTLEN + 1, DOECHO, + bh.title + 7); + if(genbuf[0]) + strcpy(newbh.title + 7, genbuf); + if(getdata_str(15, 0, "�s�O�D�W��G", genbuf, IDLEN * 3 + 3, DOECHO, + bh.BM)) { + trim(genbuf); + strcpy(newbh.BM, genbuf); + } + + if(HAS_PERM(PERM_SYSOP)) { + move(1, 0); + clrtobot(); + newbh.brdattr = setperms(newbh.brdattr, str_permboard); + move(1, 0); + clrtobot(); + } + + if(newbh.brdattr & BRD_GROUPBOARD) + strncpy(newbh.title + 5, "�U", 2); + else if(newbh.brdattr & BRD_NOTRAN) + strncpy(newbh.title + 5, "��", 2); + else + strncpy(newbh.title + 5, "��", 2); + + if(HAS_PERM(PERM_SYSOP) && !(newbh.brdattr & BRD_HIDE)) { + getdata_str(14, 0, "�]�wŪ�g�v��(Y/N)�H", ans, 4, LCECHO, "N"); + if(*ans == 'y') { + getdata_str(15, 0, "���� [R]�\\Ū (P)�o���H", ans, 4, 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_str(b_lines - 1, 0, msg_sure_ny, genbuf, 4, LCECHO, "Y"); + + if((*genbuf == 'y') && memcmp(&newbh, &bh, sizeof(bh))) { + 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); + substitute_record(fn_board, &newbh, sizeof(newbh), bid); + reset_board(bid); + log_usies("SetBoard", newbh.brdname); + } + } + return 0; +} + +extern char *msg_bid; + +/* �]�w�ݪ� */ +int m_board() { + char bname[32]; + + stand_title("�ݪO�]�w"); + make_blist(); + namecomplete(msg_bid, bname); + if(!*bname) + return 0; + m_mod_board(bname); + return 0; +} + +/* �]�w�t���ɮ� */ +int x_file() { + int aborted; + char ans[4], *fpath; + + move(b_lines - 4, 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"); + getdata(b_lines - 1, 0, " (H)�ݪO���� (I)�G�m (J)�X���e�� (K)�ͤ�d (L)�`�� [Q]�����H", ans, 3, 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 'a': + fpath = "etc/teashop"; + 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, 3, 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, 3, LCECHO); + if( ans[0] == '1' ) { unlink("etc/Welcome_login.1"); outs("ok"); } + else if( ans[0] == '2' ){ unlink("etc/Welcome_login.2"); outs("ok"); } + else if( ans[0] == '3' ){ unlink("etc/Welcome_login.3"); outs("ok"); } + else if( ans[0] == '4' ){ unlink("etc/Welcome_login.4"); outs("ok"); } + else {outs("�ҫ��w���i���e���L�k�R��"); } + pressanykey(); + return FULLUPDATE; + +#endif + + case 'h': + fpath = "etc/expire.conf"; + break; + case 'i': + fpath = "etc/domain_name_query"; + break; + case 'j': + fpath = "etc/Logout"; + break; + case 'k': + fpath = "etc/Welcome_birth"; + break; + case 'l': + fpath = "etc/feast"; + break; + default: + return FULLUPDATE; + } + aborted = vedit(fpath, NA, NULL); + prints("\n\n�t���ɮ�[%s]�G%s", fpath, + (aborted == -1) ? "������" : "��s����"); + pressanykey(); + return FULLUPDATE; +} + +extern int numboards; +extern int class_bid; + +int m_newbrd(int recover) { + boardheader_t newboard; + char ans[4]; + int bid; + char genbuf[200]; + + stand_title("�إ߷s�O"); + memset(&newboard, 0, sizeof(newboard)); + + newboard.gid = class_bid; + if (newboard.gid == 0) { + move(6, 0); + outs("�Х���ܤ@�����O�A�}�O!"); + pressanykey(); + return -1; + } + + do { + if(!getdata(3, 0, msg_bid, newboard.brdname, IDLEN + 1, 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); + + if(strlen(genbuf) >= 4) + strncpy(newboard.title, genbuf, 4); + + newboard.title[4] = ' '; + + getdata(8, 0, "�ݪO�D�D�G", genbuf, BTLEN + 1, DOECHO); + if(genbuf[0]) + strcpy(newboard.title + 7, genbuf); + setbpath(genbuf, newboard.brdname); + + if(recover) { + struct stat sb; + + if(stat(genbuf, &sb) == -1 || !(sb.st_mode & S_IFDIR)) { + outs("���ݪO�w�g�s�b! �Ш����P�^��O�W"); + pressanykey(); + return -1; + } + } else if(getbnum(newboard.brdname) > 0 || mkdir(genbuf, 0755) == -1) { + outs("���ݪO�w�g�s�b! �Ш����P�^��O�W"); + pressanykey(); + return -1; + } + + newboard.brdattr = BRD_NOTRAN; + + if(HAS_PERM(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; + + if(newboard.brdattr & BRD_GROUPBOARD) + strncpy(newboard.title + 5, "�U", 2); + else if(newboard.brdattr & BRD_NOTRAN) + strncpy(newboard.title + 5, "��", 2); + else + strncpy(newboard.title + 5, "��", 2); + + newboard.level = 0; + getdata(11, 0, "�O�D�W��G", newboard.BM, IDLEN * 3 + 3, DOECHO); + + if(HAS_PERM(PERM_SYSOP) && !(newboard.brdattr & BRD_HIDE)) { + getdata_str(14, 0, "�]�wŪ�g�v��(Y/N)�H", ans, 3, LCECHO, "N"); + if(*ans == 'y') { + getdata_str(15, 0, "���� [R]�\\Ū (P)�o���H", ans, 4, 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(); + } + } + + if((bid = getbnum("")) > 0) + { + substitute_record(fn_board, &newboard, sizeof(newboard), bid); + reset_board(bid); + } + else if(append_record(fn_board, (fileheader_t *) & newboard, + sizeof(newboard)) == -1) { + pressanykey(); + return -1; + } + else + { + addbrd_touchcache(); + } + setup_man(&newboard); + + outs("\n�s�O����"); + post_newboard(newboard.title, newboard.brdname, newboard.BM); + log_usies("NewBoard", newboard.title); + pressanykey(); + return 0; +} + +static int auto_scan(char fdata[][STRLEN], char ans[]) { + int good = 0; + int count = 0; + int i; + char temp[10]; + + if(!strncmp(fdata[2], "�p", 2) || strstr(fdata[2], "�X") + || strstr(fdata[2], "��") || strstr(fdata[2], "��")) { + ans[0] = '0'; + return 1; + } + + strncpy(temp, fdata[2], 2); + temp[2] = '\0'; + + /* �|�r */ + if(!strncmp(temp, &(fdata[2][2]), 2)) { + ans[0] = '0'; + return 1; + } + + if(strlen(fdata[2]) >= 6) { + if(strstr(fdata[2], "������")) { + 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[3], fdata[4]) || + !strcmp(fdata[3], fdata[5]) || + !strcmp(fdata[4], fdata[5])) { + ans[0] = '4'; + return 5; + } + + if(strstr(fdata[3], "�j")) { + if (strstr(fdata[3], "�x") || strstr(fdata[3], "�H") || + strstr(fdata[3], "��") || strstr(fdata[3], "�F") || + strstr(fdata[3], "�M") || strstr(fdata[3], "ĵ") || + strstr(fdata[3], "�v") || strstr(fdata[3], "�ʶ�") || + strstr(fdata[3], "����") || strstr(fdata[3], "��") || + strstr(fdata[3], "��") || strstr(fdata[3], "�F�d")) + good++; + } else if(strstr(fdata[3], "�k��")) + good++; + + if(strstr(fdata[4], "�a�y") || strstr(fdata[4], "�t�z") || + strstr(fdata[4], "�H�c")) { + ans[0] = '2'; + return 3; + } + + if(strstr(fdata[4], "��") || strstr(fdata[4], "��")) { + if(strstr(fdata[4], "��") || strstr(fdata[4], "��")) { + if(strstr(fdata[4], "��")) + good++; + } + } + + for(i = 0; fdata[5][i]; i++) { + if(isdigit(fdata[5][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; +} + +/* �B�z Register Form */ +int scan_register_form(char *regfile, int automode, int neednum) { + char genbuf[200]; + static char *logfile = "register.log"; + static char *field[] = { + "uid", "ident", "name", "career", "addr", "phone", "email", NULL + }; + static char *finfo[] = { + "�b��", "�����Ҹ�", "�u��m�W", "�A�ȳ��", "�ثe���}", + "�s���q��", "�q�l�l��H�c", NULL + }; + static char *reason[] = { + "��J�u��m�W", "�Զ�Ǯլ�t�P�~��", "��g���㪺���}���", + "�Զ�s���q��", "�T���g���U�ӽЪ�", "�Τ����g�ӽг�", NULL + }; + static char *autoid = "AutoScan"; + userec_t muser; + FILE *fn, *fout, *freg; + char fdata[7][STRLEN]; + char fname[STRLEN], buf[STRLEN]; + char ans[4], *ptr, *uid; + int n, unum; + int nSelf = 0, nAuto = 0; + + uid = cuser.userid; + sprintf(fname, "%s.tmp", regfile); + move(2, 0); + if(dashf(fname)) { + if(neednum == 0) { /* �ۤv�i Admin �Ӽf�� */ + outs("��L SYSOP �]�b�f�ֵ��U�ӽг�"); + pressanykey(); + } + return -1; + } + Rename(regfile, fname); + if((fn = fopen(fname, "r")) == NULL) { + prints("�t�ο��~�A�L�kŪ�����U�����: %s", fname); + pressanykey(); + return -1; + } + if(neednum) { /* �Q�j���f�� */ + move(1, 0); + clrtobot(); + prints("�U��㦳�����v�����H�A���U��ֿn�W�L�@�ʥ��F�A�·бz�����f %d ��\n", neednum); + prints("�]�N�O�j���G�Q�����@���ƶq�A���M�A�z�]�i�H�h�f\n�S�f�����e�A�t�Τ��|���A���X��I����"); + pressanykey(); + } + memset(fdata, 0, sizeof(fdata)); + while(fgets(genbuf, STRLEN, fn)) { + if ((ptr = (char *) strstr(genbuf, ": "))) { + *ptr = '\0'; + for(n = 0; field[n]; n++) { + if(strcmp(genbuf, field[n]) == 0) { + strcpy(fdata[n], ptr + 2); + if((ptr = (char *) strchr(fdata[n], '\n'))) + *ptr = '\0'; + } + } + } else if ((unum = getuser(fdata[0])) == 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(); + neednum--; + } else { + neednum--; + memcpy(&muser, &xuser, sizeof(muser)); + if(automode) + uid = autoid; + + if(!automode || !auto_scan(fdata, ans)) { + uid = cuser.userid; + + move(1, 0); + prints("�b����m �G%d\n", unum); + user_display(&muser, 1); + move(14, 0); + prints("\033[1;32m------------- �Я����Y��f�֨ϥΪ̸�ơA�z�٦� %d ��---------------\033[m\n", neednum); + for(n = 0; field[n]; n++) { + if(n >= 2 && n <= 5) + prints("%d.", n - 2); + else + prints(" "); + prints("%-12s�G%s\n", finfo[n], fdata[n]); + } + if(muser.userlevel & PERM_LOGINOK) { + getdata(b_lines - 1, 0, "\033[1;32m���b���w�g�������U, " + "��s(Y/N/Skip)�H\033[m[N] ", ans, 3, LCECHO); + if(ans[0] != 'y' && ans[0] != 's') + ans[0] = 'd'; + } else { + getdata(b_lines - 1, 0, + "�O�_���������(Y/N/Q/Del/Skip)�H[Y] ", + ans, 3, LCECHO); + } + nSelf++; + } else + nAuto++; + if(neednum > 0 && ans[0] == 'q') { + move(2, 0); + clrtobot(); + prints("�S�f������h�X"); + pressanykey(); + ans[0] = 's'; + } + + 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 'n': + if(ans[0] == 'n') { + for(n = 0; field[n]; n++) + prints("%s: %s\n", finfo[n], fdata[n]); + move(9, 0); + prints("�д��X�h�^�ӽЪ���]�A�� <enter> ����\n"); + for (n = 0; reason[n]; n++) + prints("%d) ��%s\n", n, reason[n]); + } else + buf[0] = ans[0]; + if(ans[0] != 'n' || + getdata(10 + n, 0, "�h�^��]�G", buf, 60, DOECHO)) + if((buf[0] - '0') >= 0 && (buf[0] - '0') < n) { + int i; + fileheader_t mhdr; + char title[128], buf1[80]; + FILE *fp; + + i = buf[0] - '0'; + strcpy(buf, reason[i]); + sprintf(genbuf, "[�h�^��]] ��%s", buf); + + sethomepath(buf1, muser.userid); + stampfile(buf1, &mhdr); + strcpy(mhdr.owner, cuser.userid); + strncpy(mhdr.title, "[���U����]", TTLEN); + mhdr.savemode = 0; + mhdr.filemode = 0; + sethomedir(title, muser.userid); + if(append_record(title, &mhdr, sizeof(mhdr)) != -1) { + fp = fopen(buf1, "w"); + fprintf(fp, "%s\n", genbuf); + fclose(fp); + } + if((fout = fopen(logfile, "a"))) { + for(n = 0; field[n]; n++) + fprintf(fout, "%s: %s\n", field[n], fdata[n]); + n = time(NULL); + fprintf(fout, "Date: %s\n", Cdate((time_t *) & n)); + fprintf(fout, "Rejected: %s [%s]\n----\n", + uid, buf); + fclose(fout); + } + break; + } + move(10, 0); + clrtobot(); + prints("�����h�^�����U�ӽЪ�"); + 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: + prints("�H�U�ϥΪ̸�Ƥw�g��s:\n"); + mail_muser(muser, "[���U���\\�o]", "etc/registered"); + muser.userlevel |= (PERM_LOGINOK | PERM_POST); + strcpy(muser.realname, fdata[2]); + strcpy(muser.address, fdata[4]); + strcpy(muser.email, fdata[6]); + sprintf(genbuf, "%s:%s:%s", fdata[5], fdata[3], uid); + strncpy(muser.justify, genbuf, REGLEN); + sethomefile(buf, muser.userid, "justify"); + log_file(buf, genbuf); + passwd_update(unum, &muser); + + if((fout = fopen(logfile, "a"))) { + for(n = 0; field[n]; n++) + fprintf(fout, "%s: %s\n", field[n], fdata[n]); + n = time(NULL); + fprintf(fout, "Date: %s\n", Cdate((time_t *) & n)); + fprintf(fout, "Approved: %s\n", uid); + fprintf(fout, "----\n"); + fclose(fout); + } + break; + } + } + } + fclose(fn); + unlink(fname); + + move(0, 0); + clrtobot(); + + move(5, 0); + prints("�z�f�F %d �����U��AAutoScan �f�F %d ��", nSelf, nAuto); + +/** DickG: �N�f�F�X����������� post �� Security �O�W ***********/ +/* DickG: �]���s�������W���ݼf�֤�סA�O�G�S�����n�d�U record ������ + strftime(buf, 200, "%Y/%m/%d/%H:%M", pt); + + strcpy(xboard, "Security"); + setbpath(xfpath, xboard); + stampfile(xfpath, &xfile); + strcpy(xfile.owner, "�t��"); + strcpy(xfile.title, "[���i] �f�ְO��"); + xfile.savemode = 'S'; + xptr = fopen(xfpath, "w"); + fprintf(xptr, "\n�ɶ��G%s + %s �f�F %d �����U��\n + AutoScan �f�F %d �����U��\n + �@�p %d ���C", + buf, cuser.userid, nSelf, nAuto, nSelf+nAuto); + fclose(xptr); + setbdir(fname, xboard); + append_record(fname, &xfile, sizeof(xfile)); + outgo_post(&xfile, xboard); + touchbtotal(getbnum(xboard)); + cuser.numposts++; +*/ +/*********************************************/ + pressanykey(); + return (0); +} + +extern char* fn_register; +extern int t_lines; + +int m_register() { + 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)�H[N] ", ans, 3, LCECHO); + if(ans[0] == 'a') + scan_register_form(fn_register, 1, 0); + else if(ans[0] == 'y') + scan_register_form(fn_register, 0, 0); + + return 0; +} + +int cat_register() { + if(system("cat register.new.tmp >> register.new") == 0 && + system("rm -f register.new.tmp") == 0) + mprints(22, 0, "OK �P~~ �~��h�İ��a!! "); + else + mprints(22, 0, "�S��kCAT�L�h�O �h�ˬd�@�U�t�Χa!! "); + pressanykey(); + return 0; +} + +static void give_id_money(char *user_id, int money, FILE *log_fp, char *mail_title, time_t t) { + char tt[TTLEN + 1] = {0}; + + if(deumoney(searchuser(user_id), money) < 0) { + move(12, 0); + clrtoeol(); + prints("id:%s money:%d ����a!!", user_id, money); + pressanykey(); + } else { + fprintf(log_fp, "%ld %s %d", t, user_id, money); + sprintf(tt, "%s : %d ptt ��", mail_title, money); + mail_id(user_id, tt, "~bbs/etc/givemoney.why", "[PTT �Ȧ�]"); + } +} + +int give_money() { + FILE *fp, *fp2; + char *ptr, *id, *mn; + char buf[200] = {0}, tt[TTLEN + 1] = {0}; + time_t t = time(NULL); + struct tm *pt = localtime(&t); + int to_all = 0, money = 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); + prints("��J���~!!"); + pressanykey(); + return 1; + } + } else { + if(vedit("etc/givemoney.txt", NA, NULL) < 0) + return 1; + } + + clear(); + getdata(0, 0, "�n�o���F��(Y/N)[N]", buf, 3, LCECHO); + if(buf[0] != 'y') + return 1; + + if(!(fp2 = fopen("etc/givemoney.log", "a"))) + return 1; + strftime(buf, 200, "%Y/%m/%d/%H:%M", pt); + fprintf(fp2, "%s\n", buf); + + getdata(1, 0, "���]�U���D �G", tt, TTLEN, DOECHO); + move(2, 0); + + prints("�s���]�U���e"); + pressanykey(); + if(vedit("etc/givemoney.why", NA, NULL) < 0) + return 1; + + stand_title("�o����..."); + if(to_all) { + extern struct uhash_t *uhash; + int i, unum; + for(unum = uhash->number, i=0; i<unum; i++) { + if(bad_user_id(uhash->userid[i])) + continue; + id = uhash->userid[i]; + give_id_money(id, money, fp2, tt, t); + } + } else { + if(!(fp = fopen("etc/givemoney.txt", "r+"))) { + fclose(fp2); + return 1; + } + while(fgets(buf, 255, fp)) { +// clear(); + if (!(ptr = strchr(buf, ':'))) + continue; + *ptr = '\0'; + id = buf; + mn = ptr + 1; + give_id_money(id, atoi(mn), fp2, tt, t); + } + fclose(fp); + } + + fclose(fp2); + pressanykey(); + return FULLUPDATE; +} diff --git a/mbbsd/announce.c b/mbbsd/announce.c new file mode 100644 index 00000000..960a45aa --- /dev/null +++ b/mbbsd/announce.c @@ -0,0 +1,1590 @@ +/* $Id: announce.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <netdb.h> +#include <unistd.h> +#include <setjmp.h> +#include <signal.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern int b_lines; +extern int p_lines; +extern int TagNum; +extern int currbid; +static void g_showmenu(gmenu_t *pm) { + static char *mytype = "�s �� ��������"; + char *title, ch; + int n, max; + item_t *item; + + showtitle("��ؤ峹", pm->mtitle); + prints(" \033[1;36m�s�� �� �D%56s\033[m", mytype); + + if(pm->num) { + n = pm->page; + max = n + p_lines; + if(max > pm->num) + max = pm->num; + while(n < max) { + item = pm->item[n++]; + title = item->title; + ch = title[1]; + prints("\n%5d. %-72.71s", n, title); + } + } else + outs("\n �m��ذϡn�|�b�l���Ѧa��������� :)"); + + move(b_lines, 1); + outs(pm->level ? + "\033[34;46m �i�O �D�j \033[31;47m (h)\033[30m���� " + "\033[31m(q/��)\033[30m���} \033[31m(n)\033[30m�s�W�峹 " + "\033[31m(g)\033[30m�s�W�ؿ� \033[31m(e)\033[30m�s���ɮ� \033[m" : + "\033[34;46m �i�\\����j \033[31;47m (h)\033[30m���� " + "\033[31m(q/��)\033[30m���} \033[31m(k��j��)\033[30m���ʴ�� " + "\033[31m(enter/��)\033[30mŪ����� \033[m"); +} + +static FILE *go_cmd(item_t *node, int *sock) { + struct sockaddr_in sin; + struct hostent *host; + char *site; + FILE *fp; + + *sock = socket(AF_INET, SOCK_STREAM, 0); + + if(*sock < 0) { + syslog(LOG_ERR, "socket(): %m"); + return NULL; + } + memset((char *)&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(node->X.G.port); + + host = gethostbyname(site = node->X.G.server); + if(host == NULL) + sin.sin_addr.s_addr = inet_addr(site); + else + memcpy(&sin.sin_addr.s_addr, host->h_addr, host->h_length); + + if(connect(*sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + syslog(LOG_ERR, "connect(): %m"); + return NULL; + } + fp = fdopen(*sock, "r+"); + if(fp != NULL) { + setbuf(fp, (char *) 0); + fprintf(fp, "%s\r\n", node->X.G.path); + fflush(fp); + } else + close(*sock); + return fp; +} + +static char *nextfield(char *data, char *field) { + register int ch; + + while((ch = *data)) { + data++; + if((ch == '\t') || (ch == '\r' && *data == '\n')) + break; + *field++ = ch; + } + *field = '\0'; + return data; +} + +extern char *str_author1; + +static FILE* my_open(char* path) { + FILE* ans = 0; + char buf[80]; + struct stat st; + time_t now = time(0); + + if(stat(path, &st) == 0 && st.st_mtime < now - 3600 * 24 * 7) { + return fopen(path, "w"); + } + + if((ans = fopen(path, "r+"))) { + fclose(ans); + return 0; + /* + return directly due to currutmp->pager > 1 mode (real copy) + */ + fgets(buf, 80, ans); + if(!strncmp(buf, str_author1, strlen(str_author1)) || + *buf == '0' || *buf == '1') { + fclose(ans); + return 0; + } + + rewind(ans); + } else + ans = fopen(path, "w"); + return ans; +} + +static jmp_buf jbuf; + +static void isig(int sig) { + longjmp(jbuf, 1); +} + +#define PROXY_HOME "proxy/" +extern userec_t cuser; +extern userinfo_t *currutmp; + +static void go_proxy(char* fpath, item_t *node, int update) { + char *ptr, *str, *server; + int ch; + static FILE *fo; + + strcpy(fpath, PROXY_HOME); + ptr = fpath + sizeof(PROXY_HOME) - 1; + str = server = node->X.G.server; + while((ch = *str)) { + str++; + if(ch == '.') { + if(!strcmp(str, "edu.tw")) + break; + } else if(ch >= 'A' && ch <= 'Z') { + ch |= 0x20; + } + *ptr++ = ch; + } + *ptr = '\0'; + mkdir(fpath, 0755); + + *ptr++ = '/'; + str = node->X.G.path; + while((ch = *str)) { + str++; + if(ch == '/') { + ch = '.'; + } + *ptr++ = ch; + } + *ptr = '\0'; + + /* expire proxy data */ + + if((fo = update ? fopen(fpath, "w") : my_open(fpath))) { + FILE *fp; + char buf[512]; + int sock; + + if(fo == NULL) + return; + + outmsg("�� �إ� proxy ��Ƴs�u�� ... "); + refresh(); + + sock = -1; + if(setjmp(jbuf)) { + if(sock != -1) + close(sock); + fseek(fo, 0, SEEK_SET); + fwrite("", 0, 0, fo); + fclose(fo); + alarm(0); + return; + } + + signal(SIGALRM, isig); + alarm(5); + fp = go_cmd(node, &sock); + alarm(0); + + str = node->title; + ch = str[1]; + if(ch == (char) 0xbc && + !(HAS_PERM(PERM_SYSOP) && currutmp->pager > 1)) { + time_t now; + + time(&now); + fprintf(fo, "�@��: %s (�s�u��ذ�)\n���D: %s\n�ɶ�: %s\n", + server, str + 3, ctime(&now) + ); + } + + while(fgets(buf, 511, fp)) { + if(!strcmp(buf, ".\r\n")) + break; + if((ptr = strstr(buf, "\r\n"))) + strcpy(ptr, "\n"); + fputs(buf, fo); + } + fclose(fo); + fclose(fp); + } +} + +static void g_additem(gmenu_t *pm, item_t *myitem) { + if(pm->num < MAX_ITEMS) { + item_t *newitem = (item_t *)malloc(sizeof(item_t)); + + memcpy(newitem, myitem, sizeof(item_t)); + pm->item[(pm->num)++] = newitem; + } +} + +static void go_menu(gmenu_t *pm, item_t *node, int update) { + FILE *fp; + char buf[512], *ptr, *title; + item_t item; + int ch; + + go_proxy(buf, node, update); + pm->num = 0; + if((fp = fopen(buf, "r"))) { + title = item.title; + while(fgets(buf, 511, fp)) { + ptr = buf; + ch = *ptr++; + if(ch != '0' && ch != '1') + continue; + + strcpy(title, "�� "); + if(ch == '1') + title[1] = (char) 0xbd; + + ptr = nextfield(ptr, title + 3); + if(!*ptr) + continue; + title[sizeof(item.title) - 1] = '\0'; + + ptr = nextfield(ptr, item.X.G.path); + if(!*ptr) + continue; + + ptr = nextfield(ptr, item.X.G.server); + if(!*ptr) + continue; + + nextfield(ptr, buf); + item.X.G.port = atoi(buf); + + g_additem(pm, &item); + } + fclose(fp); + } +} + +static int g_searchtitle(gmenu_t* pm, int rev) { + static char search_str[30] = ""; + int pos; + + if(getdata(b_lines - 1, 1,"[�j�M]����r:", search_str, 40, 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(strstr_lower(pm->item[pos]->title, search_str)) + return pos; + } while(pos != pm->now); + return pm->now; +} + +static void g_showhelp() { + clear(); + outs("\033[36m�i " BBSNAME "�s�u��ذϨϥλ��� �j\033[m\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" + "[^S] �N�峹�s��H�c\n" + "[R] ��s���\n" + "[N] �d���ɦW\n" + "[c][C][^C] �����峹/�ø��ܤW���K�峹���a��/" + "�����K��W���K���a��\n"); + pressanykey(); +} + +#define PATHLEN 256 + +static char paste_fname[200]; +extern time_t paste_time; +extern char paste_path[]; +extern char paste_title[]; +extern int paste_level; + +static void load_paste() { + struct stat st; + FILE *fp; + + if(!*paste_fname) + setuserfile(paste_fname, "paste_path"); + if(stat(paste_fname, &st) == 0 && st.st_mtime > paste_time && + (fp = fopen(paste_fname, "r"))) { + int i; + fgets(paste_path, PATHLEN, fp); + i = strlen(paste_path) - 1; + if(paste_path[i] == '\n') + paste_path[i] = 0; + fgets(paste_title, STRLEN, fp); + i = strlen(paste_title) - 1; + if(paste_title[i] == '\n') + paste_title[i] = 0; + fscanf(fp, "%d", &paste_level); + paste_time = st.st_mtime; + fclose(fp); + } +} + +static char copyfile[PATHLEN]; +static char copytitle[TTLEN+1]; +static char copyowner[IDLEN + 2]; + +void a_copyitem(char* fpath, char* title, char* owner, int mode) { + strcpy(copyfile, fpath); + strcpy(copytitle, title); + if(owner) + strcpy(copyowner, owner); + else + *copyowner = 0; + if(mode) { + outmsg("�ɮаO�����C[�`�N] ������~��R�����!"); + igetch(); + } +} + +#define FHSZ sizeof(fileheader_t) + +static void a_loadname(menu_t *pm) { + char buf[PATHLEN]; + int len; + + setadir(buf, pm->path); + len = get_records(buf, pm->header, FHSZ, pm->page+1, p_lines); + if(len < p_lines) + bzero(&pm->header[len], FHSZ*(p_lines-len)); +} + +static void a_timestamp(char *buf, time_t *time) { + struct tm *pt = localtime(time); + + sprintf(buf, "%02d/%02d/%02d", pt->tm_mon + 1, pt->tm_mday, (pt->tm_year + 1900) % 100); +} + +static void a_showmenu(menu_t *pm) { + char *title, *editor; + int n; + fileheader_t *item; + char buf[PATHLEN]; + time_t dtime; + + showtitle("��ؤ峹", pm->mtitle); + prints(" \033[1;36m�s�� �� �D%56s\033[0m", + "�s �� �� ��"); + + if(pm->num) { + setadir(buf, pm->path); + a_loadname(pm); + for(n = 0; n < p_lines && pm->page + n < pm->num; n++) { + item = &pm->header[n]; + title = item->title; + editor = item->owner; + /* Ptt ��ɶ��אּ���ɮɶ� + dtime = atoi(&item->filename[2]); + */ + sprintf(buf,"%s/%s",pm->path,item->filename); + dtime = dasht(buf); + a_timestamp(buf, &dtime); + prints("\n%6d%c %-47.46s%-13s[%s]", pm->page+n+1, + (item->filemode & FILE_BM) ?'X': + (item->filemode & FILE_HIDE) ?')':'.', + title, editor, + buf); + } + } else + outs("\n �m��ذϡn�|�b�l���Ѧa��������ؤ�... :)"); + + move(b_lines, 1); + outs(pm->level ? + "\033[34;46m �i�O �D�j \033[31;47m (h)\033[30m���� " + "\033[31m(q/��)\033[30m���} \033[31m(n)\033[30m�s�W�峹 " + "\033[31m(g)\033[30m�s�W�ؿ� \033[31m(e)\033[30m�s���ɮ� \033[m" : + "\033[34;46m �i�\\����j \033[31;47m (h)\033[30m���� " + "\033[31m(q/��)\033[30m���} \033[31m(k��j��)\033[30m���ʴ�� " + "\033[31m(enter/��)\033[30mŪ����� \033[m"); +} + +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, 40, 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; + a_loadname(pm); + } + if(strstr_lower(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("\033[36m�i " BBSNAME "���G��ϥλ��� �j\033[m\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\033[36m�i �O�D�M���� �j\033[m\n" + "[H] ������ ���}/�|��/���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] ����/�߶K/���[�峹\n" + "[^P/^A] �߶K/���[�w��'t'�аO�峹\n"); + } + + if(level >= SYSOP) { + outs("\n\033[36m�i �����M���� �j\033[m\n" + "[l] �� symbolic link\n" + "[N] �d���ɦW\n"); + } + pressanykey(); +} + +static int AnnounceSelect() { + static char xboard[20]; + char buf[20]; + char fpath[256]; + boardheader_t *bp; + + move(2, 0); + clrtoeol(); + move(3, 0); + clrtoeol(); + move(1, 0); + make_blist(); + namecomplete("��ܺ�ذϬݪO�G", buf); + if(*buf) + strcpy(xboard, buf); + if(*xboard && (bp = getbcache(getbnum(xboard)))) { + setapath(fpath, xboard); + setutmpmode(ANNOUNCE); + a_menu(xboard, fpath, + (HAS_PERM(PERM_ALLBOARD) || + (HAS_PERM(PERM_BM) && is_BM(bp->BM))) ? 1 : 0); + } + return FULLUPDATE; +} + +extern char vetitle[]; + +void gem(char* maintitle, item_t* path, int update) { + gmenu_t me; + int ch; + char fname[PATHLEN]; + + strncpy(me.mtitle, maintitle, 40); + me.mtitle[40] = 0; + go_menu(&me, path, update); + + /* ��ذ�-tree ���������c�ݩ� cuser ==> BM */ + + me.level = 0; + me.page = 9999; + me.now = 0; + for(;;) { + if(me.now >= me.num && me.num > 0) + me.now = me.num - 1; + else if(me.now < 0) + me.now = 0; + + if(me.now < me.page || me.now >= me.page + p_lines) { + me.page = me.now - (me.now % p_lines); + g_showmenu(&me); + } + ch = cursor_key(2 + me.now - me.page, 0); + if(ch == 'q' || ch == 'Q' || ch == KEY_LEFT) + break; + + if(ch >= '0' && ch <= '9') { + if((ch = search_num(ch, me.num)) != -1) + me.now = ch; + me.page = 9999; + 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 '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 'h': + g_showhelp(); + me.page = 9999; + break; + case '?': + case '/': + me.now = g_searchtitle(&me, ch == '?'); + me.page = 9999; + break; + case 'N': + if(HAS_PERM(PERM_SYSOP)) { + go_proxy(fname, me.item[me.now], 0); + move(b_lines - 1, 0); + outs(fname); + pressanykey(); + me.page = 9999; + } + break; + case 'c': + case 'C': + case Ctrl('C'): + if(me.now < me.num) { + item_t *node = me.item[me.now]; + char *title = node->title; + int mode = title[1]; + + load_paste(); + if(mode == (char) 0xbc || ch == Ctrl('C')) { + if(mode == (char) 0xbc) + go_proxy(fname, node, 0); + if(ch == Ctrl('C') && *paste_path && paste_level) { + char newpath[PATHLEN]; + fileheader_t item; + + strcpy(newpath, paste_path); + if(mode == (char) 0xbc) { + stampfile(newpath, &item); + unlink(newpath); + Link(fname, newpath); + } else + stampdir(newpath, &item); + strcpy(item.owner, cuser.userid); + sprintf(item.title, "%s%.72s", + (currutmp->pager > 1) ? "" : + (mode == (char) 0xbc) ? "�� " : "�� ", + title + 3); + strcpy(strrchr(newpath, '/') + 1, ".DIR"); + append_record(newpath, &item, FHSZ); + if(++me.now >= me.num) + me.now = 0; + break; + } + if(mode == (char) 0xbc) { + a_copyitem(fname, + title + ((currutmp->pager > 1) ? 3 : 0), + 0, 1); + if(ch == 'C' && *paste_path) { + setutmpmode(ANNOUNCE); + a_menu(paste_title, paste_path, paste_level); + } + me.page = 9999; + } else + bell(); + } + } + break; + case Ctrl('B'): + m_read(); + me.page = 9999; + break; + case Ctrl('I'): + t_idle(); + me.page = 9999; + break; + case 's': + AnnounceSelect(); + me.page = 9999; + break; + case '\n': + case '\r': + case KEY_RIGHT: + case 'r': + case 'R': + if(me.now < me.num) { + item_t *node = me.item[me.now]; + char *title = node->title; + int mode = title[1]; + int update = (ch == 'R') ? 1 : 0; + + title += 3; + + if(mode == (char) 0xbc) { + int more_result; + + go_proxy(fname, node, update); + strcpy(vetitle, title); + while((more_result = more(fname, YEA))) { + if(more_result == 1) { + if(--me.now < 0) { + me.now = 0; + break; + } + } else if(more_result == 3) { + if(++me.now >= me.num) { + me.now = me.num - 1; + break; + } + } else + break; + node = me.item[me.now]; + if(node->title[1] != (char) 0xbc) + break; + go_proxy(fname, node, update); + strcpy(vetitle, title); + } + } else if(mode == (char) 0xbd) { + gem(title, node, update); + } + me.page = 9999; + } + break; + } + } + for(ch = 0; ch < me.num; ch++) + free(me.item[ch]); +} + +extern char *msg_fwd_ok; +extern char *msg_fwd_err1; +extern char *msg_fwd_err2; + +static void a_forward(char *path, fileheader_t *pitem, int mode) { + fileheader_t fhdr; + + strcpy(fhdr.filename, pitem->filename); + strcpy(fhdr.title, pitem->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, 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*/ + strcpy(pm->header[pm->now - pm->page].filename, myheader->filename); +} + +#define ADDITEM 0 +#define ADDGROUP 1 +#define ADDGOPHER 2 +#define ADDLINK 3 +extern char currboard[]; + +static void a_newitem(menu_t *pm, int mode) { + static char *mesg[4] = { + "[�s�W�峹] �п�J���D�G", /* ADDITEM */ + "[�s�W�ؿ�] �п�J���D�G", /* ADDGROUP */ + "[�s�W�s�u] �п�J���D�G", /* ADDGOPHER */ + "�п�J���D�G" /* ADDLINK */ + }; + + char fpath[PATHLEN], buf[PATHLEN], lpath[PATHLEN]; + fileheader_t item; + int d; + + strcpy(fpath, pm->path); + + switch(mode) { + case ADDITEM: + stampfile(fpath, &item); + strcpy(item.title, "�� "); /* A1BA */ + break; + + case ADDGROUP: + stampdir(fpath, &item); + strcpy(item.title, "�� "); /* A1BB */ + break; + case ADDGOPHER: + bzero(&item, sizeof(item)); + strcpy(item.title, "�� "); /* A1BB */ + if(!getdata(b_lines - 2, 1, "��JURL��}�G", + item.filename+2,61, DOECHO)) + return; + break; + case ADDLINK: + stamplink(fpath, &item); + if (!getdata(b_lines - 2, 1, "�s�W�s�u�G", buf, 61, DOECHO)) + return; + if(invalid_pname(buf)) { + unlink(fpath); + outs("�ت��a���|���X�k�I"); + igetch(); + return; + } + + item.title[0] = 0; + for(d = 0; d <= 3; d++) { + switch(d) { + case 0: + sprintf(lpath, "%s%s%s/%s", + BBSHOME, "/man/boards/",currboard , buf); + break; + case 1: + sprintf(lpath, "%s%s%s", + BBSHOME, "/man/boards/" , buf); + break; + case 2: + sprintf(lpath, "%s%s%s", + BBSHOME, "/" , buf); + break; + case 3: + sprintf(lpath, "%s%s%s", + BBSHOME, "/etc/" , buf); + break; + } + if(dashf(lpath)) { + strcpy(item.title, "�� "); /* A1B3 */ + break; + } else if (dashd(lpath)) { + strcpy(item.title, "�� "); /* A1B4 */ + break; + } + if(!HAS_PERM(PERM_BBSADM) && d==1) + break; + } + + if(!item.title[0]) { + unlink(fpath); + outs("�ت��a���|���X�k�I"); + igetch(); + return; + } + } + + if(!getdata(b_lines - 1, 1, mesg[mode], &item.title[3], 55, DOECHO)) { + if(mode == ADDGROUP) + rmdir(fpath); + else if(mode != ADDGOPHER) + unlink(fpath); + return; + } + + switch(mode) { + case ADDITEM: + if(vedit(fpath, 0, NULL) == -1) { + unlink(fpath); + pressanykey(); + return; + } + break; + case ADDLINK: + unlink(fpath); + if(symlink(lpath, fpath) == -1) { + outs("�L�k�إ� symbolic link"); + igetch(); + return; + } + break; + case ADDGOPHER: + strcpy(item.date, "70"); + strncpy(item.filename, "H.",2); + break; + } + + strcpy(item.owner, cuser.userid); + a_additem(pm, &item); +} + +static void a_pasteitem(menu_t *pm, int mode) { + char newpath[PATHLEN]; + char buf[PATHLEN]; + char ans[2]; + int i; + fileheader_t item; + + move(b_lines - 1, 1); + if(copyfile[0]) { + if(dashd(copyfile)) { + for(i = 0; copyfile[i] && copyfile[i] == pm->path[i]; i++); + if(!copyfile[i]) { + outs("�N�ؿ����i�ۤv���l�ؿ����A�|�y���L�a�j��I"); + igetch(); + return; + } + } + if(mode) { + sprintf(buf, "�T�w�n����[%s]��(Y/N)�H[N] ", copytitle); + getdata(b_lines - 1, 1, buf, ans, 3, LCECHO); + } else + ans[0]='y'; + if(ans[0] == 'y') { + strcpy(newpath, pm->path); + + if(*copyowner) { + char* fname = strrchr(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)); + strcpy(item.filename, fname + 1); + memcpy(copytitle, "��", 2); + if(HAS_PERM(PERM_BBSADM)) + Link(copyfile, newpath); + else { + sprintf(buf, "/bin/cp %s %s", copyfile, newpath); + system(buf); + } + } else if(dashf(copyfile)) { + stampfile(newpath, &item); + memcpy(copytitle, "��", 2); + sprintf(buf, "/bin/cp %s %s", copyfile, newpath); + } else if(dashd(copyfile)) { + stampdir(newpath, &item); + memcpy(copytitle, "��", 2); + sprintf(buf, "/bin/cp -r %s/* %s/.D* %s", copyfile, copyfile, + newpath); + } else { + outs("�L�k�����I"); + igetch(); + return; + } + strcpy(item.owner, *copyowner ? copyowner : cuser.userid); + strcpy(item.title, copytitle); + if(!*copyowner) + system(buf); + a_additem(pm, &item); + copyfile[0] = '\0'; + } + } else { + outs("�Х����� copy �R�O��A paste"); + igetch(); + } +} + +static void a_appenditem(menu_t *pm, int isask) { + char fname[PATHLEN]; + char buf[ANSILINELEN]; + char ans[2] = "y"; + FILE *fp, *fin; + + move(b_lines - 1, 1); + if(copyfile[0]) { + if(dashf(copyfile)) { + sprintf(fname, "%s/%s", pm->path, + pm->header[pm->now-pm->page].filename); + if(dashf(fname)) { + if(isask) { + sprintf(buf, "�T�w�n�N[%s]���[��(Y/N)�H[N] ", + copytitle); + getdata(b_lines - 2, 1, buf, ans, 3, LCECHO); + } + if(ans[0] == 'y') { + if((fp = fopen(fname, "a+"))) { + if((fin = fopen(copyfile, "r"))) { + 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, 3, LCECHO); + while(fgets(buf, sizeof(buf), fin)) { + if((ans[0] == 'n' ) && + !strcmp(buf, "--\n")) + break; + fputs(buf, fp); + } + fclose(fin); + copyfile[0] = '\0'; + } + fclose(fp); + } + } + } else { + outs("�ɮפ��o���[�I"); + igetch(); + } + } else { + outs("���o���[��ӥؿ����ɮ�I"); + igetch(); + } + } else { + outs("�Х����� copy �R�O��A append"); + igetch(); + } +} + +static int a_pastetagpost(menu_t *pm, int mode) { + extern int TagNum; + extern void EnumTagFhdr(); + extern void UnTagger(int locus); + fileheader_t fhdr; + int ans = 0, ent=0, tagnum; + char title[TTLEN + 1]= "�� "; + char dirname[200],buf[200]; + + setbdir(dirname, currboard); + tagnum = TagNum; + + if (!tagnum) return ans; + + while (tagnum--) + { + EnumTagFhdr (&fhdr, dirname, ent++); + setbfile (buf, currboard, fhdr.filename); + + if (dashf (buf)) + { + strncpy(title+3, fhdr.title, TTLEN-3); + title[TTLEN] = '\0'; + 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[4]; + int num, max, min; + char buf[PATHLEN]; + int fail; + + sprintf(buf, "�п�J�� %d �ﶵ���s���ǡG", pm->now + 1); + if(!getdata(b_lines - 1, 1, buf, newnum, 6, 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[256]; + + sprintf(fname,"%s/.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; + + sprintf(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�w�n�R������ذϳs�u��(Y/N)�H[N] ", + ans, 3, 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�w�n�R���� symbolic link ��(Y/N)�H[N] ", + ans, 3, 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�w�n�R�����ɮ�(Y/N)�H[N] ", ans, 3, + LCECHO); + if(ans[0] != 'y') + return; + if(delete_record(buf, FHSZ, pm->now + 1) == -1) + return; + + setbpath(buf, "deleted"); + stampfile(buf, &backup); + strcpy(backup.owner, cuser.userid); + strcpy(backup.title,pm->header[pm->now - pm->page].title + 2); + backup.savemode = 'D'; + + sprintf(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�w�n�R����ӥؿ���(Y/N)�H[N] ", ans, 3, + LCECHO); + if(ans[0] != 'y') + return; + if(delete_record(buf, FHSZ, pm->now + 1) == -1) + return; + + setapath(buf, "deleted"); + stampdir(buf, &backup); + + sprintf(cmd, "rm -rf %s;/bin/mv -f %s %s",buf,fpath,buf); + system(cmd); + + strcpy(backup.owner, cuser.userid); + strcpy(backup.title,pm->header[pm->now - pm->page].title +2); + setapath(buf, "deleted"); + setadir(buf,buf); + append_record(buf, &backup, sizeof(backup)); + } else { /* Ptt �l�������� */ + getdata(b_lines - 1, 1, "�z�T�w�n�R�����l�������ض�(Y/N)�H[N] ", + ans, 3, LCECHO); + if(ans[0] != 'y') + return; + if(delete_record(buf, FHSZ, pm->now + 1) == -1) + return; + } + pm->num--; +} + +static void a_newtitle(menu_t *pm) { + char buf[PATHLEN]; + fileheader_t item; + + memcpy(&item, &pm->header[pm->now - pm->page], FHSZ); + strcpy(buf,item.title + 3); + if(getdata_buf(b_lines - 1, 1, "�s���D�G", buf, 60, DOECHO)) { + strcpy(item.title + 3, buf); + setadir(buf, pm->path); + substitute_record(buf, &item, FHSZ, pm->now + 1); + } +} +static void a_hideitem(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(menu_t *pm) { + char buf[PATHLEN]; + fileheader_t item; + + memcpy(&item, &pm->header[pm->now - pm->page], FHSZ); + sprintf(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(menu_t *pm) { + char buf[PATHLEN]; + int len; + int i; + int sym; + + move(b_lines - 1, 1); + sprintf(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(HAS_PERM(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) { + pressanykey(); + move(b_lines - 1, 1); + prints("�� 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(); +} + +static char *a_title; + +static void atitle() { + showtitle("��ؤ峹", a_title); + outs("[��]���} [��]�\\Ū [^P]�o���峹 [b]�Ƨѿ� [d]�R�� [q]��ذ� " + "[TAB]��K [h]elp\n\033[7m �s�� �� �� �@ �� " + "�� �� �� �D\033[m"); +} + +extern char currtitle[]; + +char trans_buffer[256]; +extern char quote_file[]; +extern unsigned int currstat; + +static int isvisible_man(menu_t *me) +{ + fileheader_t *fhdr = &me->header[me->now-me->page]; + if( me->level<MANAGER && ((fhdr->filemode & FILE_BM) || + ((fhdr->filemode & FILE_HIDE) && + hbflcheck(currbid, currutmp->uid)))) + return 0; + return 1; +} +int a_menu(char *maintitle, char *path, int lastlevel) { + static char Fexit; + menu_t me; + char fname[PATHLEN]; + int ch, returnvalue = FULLUPDATE; + + trans_buffer[0] = 0; + + Fexit = 0; + me.header = (fileheader_t *)calloc(p_lines, FHSZ); + me.path = path; + strcpy(me.mtitle, maintitle); + setadir(fname, me.path); + me.num = get_num_records(fname, FHSZ); + + /* ��ذ�-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 + p_lines) { + me.page = me.now - ((me.page == 10000 && me.now > p_lines / 2) ? + (p_lines / 2) : (me.now % p_lines)); + a_showmenu(&me); + } + + 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 '/': + 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('C'): + cal(); + me.page = 9999; + break; + + case Ctrl('I'): + t_idle(); + me.page = 9999; + break; + + case 's': + AnnounceSelect(); + me.page = 9999; + break; + + case 'e': + case 'E': + sprintf(fname, "%s/%s", path, me.header[me.now-me.page].filename); + if(dashf(fname) && me.level >= MANAGER) { + *quote_file = 0; + if(vedit(fname, NA, NULL) != -1) { + char fpath[200]; + fileheader_t fhdr; + + strcpy(fpath, path); + stampfile(fpath, &fhdr); + unlink(fpath); + Rename(fname, fpath); + strcpy(me.header[me.now-me.page].filename, fhdr.filename); + strcpy(me.header[me.now-me.page].owner, cuser.userid); + setadir(fpath, path); + substitute_record(fpath, me.header+me.now-me.page, + sizeof(fhdr), me.now + 1); + } + me.page = 9999; + } + break; + + case 'c': + if(me.now < me.num) { + if(!isvisible_man(&me)) break; + sprintf(fname, "%s/%s", path, + me.header[me.now-me.page].filename); + a_copyitem(fname, me.header[me.now-me.page].title, 0, 1); + me.page = 9999; + 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; + sprintf(fname, "%s/%s", path, fhdr->filename); + if(*fhdr->filename == 'H' && fhdr->filename[1] == '.') { + item_t item; + strcpy(item.X.G.server, fhdr->filename + 2); + strcpy(item.X.G.path, "1/"); + item.X.G.port = 70; + gem(fhdr->title, &item, (ch == 'R') ? 1 : 0); + } else if (dashf(fname)) { + int more_result; + + while((more_result = more(fname, YEA))) { + /* Ptt �d�����F plugin */ + if(currstat == EDITEXP || currstat == OSONG) { + char ans[4]; + + move(22, 0); + clrtoeol(); + getdata(22, 1, + currstat == EDITEXP ? + "�n��d�� Plugin ��峹��?[y/N]": + "�T�w�n�I�o���q��?[y/N]", + ans, 3, LCECHO); + if(ans[0]=='y') { + strcpy(trans_buffer,fname); + Fexit = 1; + free(me.header); + if(currstat == OSONG){ + log_file(FN_USSONG,fhdr->title); + } + return FULLUPDATE; + } + } + if(more_result == 1) { + if(--me.now < 0) { + me.now = 0; + break; + } + } else if(more_result == 3) { + if(++me.now >= me.num) { + me.now = me.num - 1; + break; + } + } else + break; + if(!isvisible_man(&me)) break; + sprintf(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); + /* Ptt �j�O���Xrecursive */ + if(Fexit) { + free(me.header); + return FULLUPDATE; + } + } + me.page = 9999; + } + break; + + case 'F': + case 'U': + sprintf(fname, "%s/%s", path, me.header[me.now-me.page].filename); + if(me.now < me.num && HAS_PERM(PERM_BASIC) && dashf(fname)) { + a_forward(path, &me.header[me.now-me.page], ch /*== 'U'*/); + /*By CharlieL*/ + } else + outmsg("�L�k��H������"); + + me.page = 9999; + refresh(); + sleep(1); + break; + } + + if(me.level >= MANAGER) { + int page0 = me.page; + + switch(ch) { + case 'n': + a_newitem(&me, ADDITEM); + me.page = 9999; + break; + case 'g': + a_newitem(&me, ADDGROUP); + me.page = 9999; + break; + case 'G': + a_newitem(&me, ADDGOPHER); + 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; + default: + me.page = page0; + break; + } + + 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; + } + } + + if(me.level == SYSOP) { + switch(ch) { + case 'l': + a_newitem(&me, ADDLINK); + me.page = 9999; + break; + case 'N': + a_showname(&me); + me.page = 9999; + break; + } + } + } + free(me.header); + return returnvalue; +} + +static char *mytitle = BBSNAME "�G�i��"; + +int Announce() { + setutmpmode(ANNOUNCE); + a_menu(mytitle, "man", + ((HAS_PERM(PERM_SYSOP) || HAS_PERM(PERM_ANNOUNCE)) ? SYSOP : + NOBODY)); + return 0; +} diff --git a/mbbsd/args.c b/mbbsd/args.c new file mode 100644 index 00000000..4d1d6ceb --- /dev/null +++ b/mbbsd/args.c @@ -0,0 +1,62 @@ +/* $Id: args.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#ifdef HAVE_SETPROCTITLE + +void initsetproctitle(int argc, char **argv, char **envp) { +} + +#else + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> + +char **Argv = NULL; /* pointer to argument vector */ +char *LastArgv = NULL; /* end of argv */ +extern char **environ; + +void initsetproctitle(int argc, char **argv, char **envp) { + register int i; + + /* Move the environment so setproctitle can use the space at + the top of memory. */ + for(i = 0; envp[i]; i++); + environ = malloc(sizeof(char *) * (i + 1)); + for(i = 0; envp[i]; i++) + environ[i] = strdup(envp[i]); + environ[i] = NULL; + + /* Save start and extent of argv for setproctitle. */ + Argv = argv; + if(i > 0) + LastArgv = envp[i - 1] + strlen(envp[i - 1]); + else + LastArgv = argv[argc - 1] + strlen(argv[argc - 1]); +} + +static void do_setproctitle(const char *cmdline) { + char buf[256], *p; + int i; + + strncpy(buf, cmdline, 256); + buf[255] = '\0'; + i = strlen(buf); + if(i > LastArgv - Argv[0] - 2) { + i = LastArgv - Argv[0] - 2; + } + strcpy(Argv[0], buf); + p = &Argv[0][i]; + while(p < LastArgv) + *p++='\0'; + Argv[1] = NULL; +} + +void setproctitle(const char* format, ...) { + char buf[256]; + va_list args; + va_start(args, format); + vsprintf(buf, format,args); + do_setproctitle(buf); + va_end(args); +} +#endif diff --git a/mbbsd/bbcall.c b/mbbsd/bbcall.c new file mode 100644 index 00000000..d7b2d33b --- /dev/null +++ b/mbbsd/bbcall.c @@ -0,0 +1,268 @@ +/* $Id: bbcall.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <netdb.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +#define SERVER_0941 "www.chips.com.tw" +#define SERVER_0943 "www.pager.com.tw" +#define SERVER_0948 "www.fitel.net.tw" +#define SERVER_0947 "www.hoyard.com.tw" +#define SERVER_0945 "203.73.181.254" + +#define CGI_0948 "/cgi-bin/Webpage.dll" +#define CGI_0941 "/cgi-bin/paging1.pl" +#define CGI_0947 "/scripts/fp_page1.dll" +#define CGI_0945 "/Scripts/fiss/PageForm.exe" +#define CGI_0943 "/tpn/tpnasp/dowebcall.asp" + +#define CGI_RAILWAY "http://www.railway.gov.tw/cgi-bin/timetk.cgi" + +#define REFER_0943 "http://www.pager.com.tw/tpn/webcall/webcall.asp" +#define REFER_0948 "http://www.fitel.net.tw/html/svc03.htm" +#define REFER_0941 "http://www.chips.com.tw:9100/WEB2P/page_1.htm" +#define REFER_0947 "http://web1.hoyard.com.tw/freeway/freewayi.html" +#define REFER_0945 "http://203.73.181.254/call.HTM" + +static void pager_msg_encode(char *field, char *buf) { + char *cc = field; + unsigned char *p; + + for(p = (unsigned char *)buf; *p; p++) { + if((*p >= '0' && *p <= '9') || + (*p >= 'A' && *p <= 'Z') || + (*p >= 'a' && *p <= 'z') || + *p == ' ') + *cc++ = *p == ' ' ? '+' : (char)*p; + else { + sprintf(cc, "%%%02X", (int)*p); + cc += 3; + } + } + *cc = 0; +} + +static void gettime(int flag, int *Year, int *Month, int *Day, int *Hour, + int *Minute) { + char ans[5]; + + do { + getdata(10, 0, "�~[20-]:", ans, 3, LCECHO); + *Year = atoi(ans); + } while(*Year < 00 || *Year > 02); + do { + getdata(10, 15, "��[1-12]:", ans, 3, LCECHO); + } while(!IsSNum(ans) || (*Month = atoi(ans)) > 12 || *Month < 1); + do { + getdata(10,30, "��[1-31]:", ans, 3, LCECHO); + } while(!IsSNum(ans) || (*Day = atoi(ans)) > 31 || *Day < 1); + do { + getdata(10,45, "��[0-23]:", ans, 3, LCECHO); + } while(!IsSNum(ans) || (*Hour = atoi(ans)) > 23 || *Hour < 0); + do { + getdata(10,60, "��[0-59]:", ans, 3, LCECHO); + } while(!IsSNum(ans) || (*Minute=atoi(ans))>59 || *Minute<0); + if(flag == 1) + *Year-=11; +} + +#define hpressanykey(a) {move(22, 0); prints(a); pressanykey();} + +static int Connect(char *s, char *server) { + FILE *fp = fopen(BBSHOME "/log/bbcall.log", "a"); + int sockfd; + char result[2048]; + struct sockaddr_in serv_addr; + struct hostent *hp; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(sockfd < 0) + return 0; + + memset((char *)&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + + if((hp = gethostbyname(server)) == NULL) + return 0; + + memcpy(&serv_addr.sin_addr, hp->h_addr, hp->h_length); + + if(!strcmp(server, SERVER_0941)) + serv_addr.sin_port = htons(9100); + else + serv_addr.sin_port = htons(80); + + if(connect(sockfd, (struct sockaddr *) &serv_addr, sizeof serv_addr)) { + hpressanykey("�L�k�P���A�����o�s���A�ǩI����"); + return 0; + } else { + mprints(20, 0, "\033[1;33m���A���w�g�s���W�A�еy��" + ".....................\033[m"); + refresh(); + } + + write(sockfd, s, strlen(s)); + shutdown(sockfd, 1); + + while(read(sockfd, result, sizeof(result)) > 0) { + fprintf(fp, "%s\n", result); + fflush(fp); + if(strstr(result, "���T") || + strstr(result,"����") || + strstr(result,"�A��") || + strstr(result,"�� �� �^ ��") || + strstr(result, "�w����") || + strstr(result,"�ǰe��")) { + close(sockfd); + hpressanykey("���Q�e�X�ǩI"); + return 0; + } + memset(result, 0, sizeof(result)); + } + fclose(fp); + close(sockfd); + hpressanykey("�L�k���Q�e�X�ǩI"); + return 0; +} + +#define PARA \ +"Connection: Keep-Alive\r\n"\ +"User-Agent: Lynx/2.6 libwww-FM/2.14\r\n"\ +"Content-type: application/x-www-form-urlencoded\r\n"\ +"Accept: text/html, text/plain, application/x-wais-source, "\ +"application/html, */*;q=0.001\r\n"\ +"Accept-Encoding: gzip\r\n"\ +"Accept-Language: en\r\n"\ +"Accept-Charset: iso-8859-1,*,utf-8\r\n" + +static void halpha0943(char* CoId) { + char tmpbuf[64],ans[2]; + char ID[8]; + char Msg[64], atrn[512], sendform[1024]; + int Year = 99, Month = 1, Day = 15, Hour = 13, Minute = 8; + + sprintf(tmpbuf, "\033[1;37m�п�J�z�n�ǩI�����X\033[m : %s-", CoId); + if(!getdata(7,0, tmpbuf, ID, 7, LCECHO) || + !getdata(8,0, "\033[1;37m�п�J�ǩI�T��\033[m�G", tmpbuf, 63, LCECHO)) { + hpressanykey("���ǩI"); + return; + } + pager_msg_encode(Msg,tmpbuf); + getdata(9, 0, "\033[1;37m�p�G�A�n���W�e�Ы� '1' " + "�p�G�n�w�ɰe�Ы� '2': \033[m", ans, 2, LCECHO); + + if(ans[0] != '1') + gettime(0, &Year, &Month, &Day, &Hour, &Minute); + + sprintf(atrn, "CoId=%s&ID=%s&Year=19%02d&Month=%02d&Day=%02d" + "&Hour=%02d&Minute=%02d&Msg=%s", + CoId, ID,Year,Month,Day,Hour,Minute,Msg); + sprintf(sendform, "POST %s HTTP/1.0\nReferer: " + "%s\n%sContent-length:%d\n\n%s", + CGI_0943, REFER_0943, PARA, strlen(atrn), atrn); + Connect(sendform, SERVER_0943); + return ; +} + +static void hcall0941() { + char ans[2]; + char PAGER_NO[8], TRAN_MSG[18], TIME[8]; + char trn[512], sendform[512]; + int year = 98, month = 12, day = 4, hour = 13, min = 8; + + if(!getdata(7, 0, "\033[1;37 �бz��J�z�n�ǩI�����X : 0941- \033[m", + PAGER_NO, 7, LCECHO) || + !getdata(8, 0, "\033[1;37m�п�J�ǩI�T��\033[m�G", trn, 17, LCECHO)) { + hpressanykey("���ǩI"); + return; + } + pager_msg_encode(TRAN_MSG,trn); + getdata(9,0, "\033[1;37m�p�G�A�n���W�e�Ы� '1' " + "�p�G�n�w�ɰe�Ы� '2': \033[m", ans, 2, LCECHO); + if(ans[0] != '1') { + strcpy(TIME,"DELAY"); + gettime(0, &year, &month, &day, &hour, &min); + } else + strcpy(TIME,"NOW"); + sprintf(trn,"PAGER_NO=%s&TRAN_MSG=%s&MSG_TYPE=NUMERIC&%s=1" + "&year=19%02d&month=%02d&day=%02d&hour=%02d&min=%02d", + PAGER_NO, TRAN_MSG, TIME,year,month,day,hour,min); + + sprintf(sendform, "POST %s HTTP/1.0\nReferer: %s\n%s" + "Content-length:%d\n\n%s", + CGI_0941, REFER_0941, PARA, strlen(trn), trn); + + Connect(sendform, SERVER_0941); + return ; +} + +static void hcall0948() { + int year = 87, month = 12, day = 19, hour = 12, min = 0, ya = 0; + char svc_no[8], message[64], trn[256], sendform[512], ans[3]; + + move(7,0); + clrtoeol(); + + if(!getdata(7, 0, "\033[1;37m�п�J�z�n�ǩI�����X\033[m�G0948-", + svc_no, 7, LCECHO) || + !getdata(8, 0, "\033[1;37m�п�J�ǩI�T��\033[m�G", trn, 61, LCECHO)) { + hpressanykey("���ǩI"); + return; + } + pager_msg_encode(message, trn); + getdata(9, 0, "\033[1;37m�p�G�A�n���W�e�Ы� '1' " + "�p�G�n�w�ɰe�Ы� '2'\033[m: ", ans, 2, LCECHO); + if(ans[0] != '1') { + gettime(1, &year, &month, &day, &hour, &min); + ya = 1; + } + + sprintf(trn, "MfcISAPICommand=SinglePage&svc_no=%s&reminder=%d" + "&year=%02d&month=%02d&day=%02d&hour=%02d&min=%02d&message=%s", + svc_no, ya, year, month, day, hour, min, message); + + sprintf(sendform, "GET %s?%s Http/1.0\n\n", CGI_0948, trn); + + Connect(sendform, SERVER_0948); + return; +} + +int main_bbcall() { + char ch[2]; + + clear(); + move(0, 30); + prints("\033[1;37;45m �G�G��� \033[m"); + move(3, 0); + prints("\033[1;31m �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�{\033[m\n"); + prints("\033[1;33m (1)0941 (2)0943 (3)0946 " + " (4)0948 \033[m\n"); + prints("\033[1;31m �|�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�}\033[m\n"); + getdata(7, 8, "\033[1;37m�A�����? [1-4]\033[m", ch, 2, LCECHO); + + switch(ch[0]) { + case '1': + hcall0941(); + break; + case '2': + halpha0943("0943"); + break; + case '3': + halpha0943("0946"); + break; + case '4': + hcall0948(); + break; + } + return 0; +} diff --git a/mbbsd/bbs.c b/mbbsd/bbs.c new file mode 100644 index 00000000..15db1c91 --- /dev/null +++ b/mbbsd/bbs.c @@ -0,0 +1,1904 @@ +/* $Id: bbs.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "modes.h" +#include "common.h" +#include "proto.h" + +static int g_board_names(boardheader_t *fhdr) { + AddNameList(fhdr->brdname); + return 0; +} + +extern userec_t cuser; +extern void touchdircache(int bid); +extern int TagNum; + +static void mail_by_link(char* owner, char* title, char* path) { + char genbuf[200]; + fileheader_t mymail; + + sprintf(genbuf,BBSHOME"/home/%c/%s", cuser.userid[0], cuser.userid); + stampfile(genbuf, &mymail); + strcpy(mymail.owner, owner); + sprintf(mymail.title, title); + mymail.savemode = 0; + unlink(genbuf); + Link(path, genbuf); + sprintf(genbuf,BBSHOME"/home/%c/%s/.DIR",cuser.userid[0],cuser.userid); + + append_record(genbuf, &mymail, sizeof(mymail)); +} + +extern int usernum; + +void anticrosspost() { + char buf[200]; + time_t now = time(NULL); + + sprintf(buf, + "\033[1;33;46m%s \033[37;45mcross post �峹 \033[37m %s\033[m", + cuser.userid, ctime(&now)); + log_file("etc/illegal_money", buf); + + post_violatelaw(cuser.userid, "Ptt�t��ĵ��", "Cross-post", "�@��B��"); + cuser.userlevel |= PERM_VIOLATELAW; + cuser.vl_count ++; + mail_by_link("Pttĵ���", "Cross-Post�@��", + BBSHOME "/etc/crosspost.txt"); + passwd_update(usernum, &cuser); + exit(0); +} + +/* Heat CharlieL*/ +int save_violatelaw() { + char buf[128], ok[3]; + + setutmpmode(VIOLATELAW); + clear(); + stand_title("ú�@�椤��"); + + if(!(cuser.userlevel & PERM_VIOLATELAW)) { + mprints(22, 0, "\033[1;31m�A�L���? �A�S�S���Q�}�@��~~\033[m"); + pressanykey(); + return 0; + } + + reload_money(); + if(cuser.money < (int)cuser.vl_count*1000) { + sprintf(buf, "\033[1;31m�o�O�A�� %d ���H�ϥ����k�W" + "����ú�X %d $Ptt ,�A�u�� %d ��, ��������!!\033[m", + (int)cuser.vl_count, (int)cuser.vl_count * 1000, cuser.money); + mprints(22, 0, buf); + pressanykey(); + return 0; + } + + move(5,0); + prints("\033[1;37m�A���D��? �]���A���H�k " + "�w�g�y���ܦh�H�����K\033[m\n"); + prints("\033[1;37m�A�O�_�T�w�H�ᤣ�|�A�ǤF�H\033[m\n"); + + if(!getdata(10,0,"�T�w�ܡH[y/n]:", ok, 2, LCECHO) || + ok[0] == 'n' || ok[0] == 'N') { + mprints(22,0,"\033[1;31m���A�Q�q�F�A�ӧa!! " + "�ڬ۫H�A���|�������諸~~~\033[m"); + pressanykey(); + return 0; + } + + sprintf(buf, "�o�O�A�� %d ���H�k ����ú�X %d $Ptt", + cuser.vl_count, cuser.vl_count*1000); + mprints(11,0,buf); + + if(!getdata(10, 0, "�n�I��[y/n]:", ok, 2, LCECHO) || + ok[0] == 'N' || ok[0] == 'n') { + + mprints(22,0, "\033[1;31m �� �s���� �A�ӧa!!!\033[m"); + pressanykey(); + return 0; + } + + demoney(-1000*cuser.vl_count); + cuser.userlevel &= (~PERM_VIOLATELAW); + passwd_update(usernum, &cuser); + return 0; +} + +void make_blist() { + CreateNameList(); + apply_boards(g_board_names); +} + +extern int currbid; +extern char currBM[]; +extern int currmode; +extern char currboard[]; +static time_t board_note_time; +static char *brd_title; + +void set_board() { + boardheader_t *bp; + + bp = getbcache(currbid); + board_note_time = bp->bupdate; + brd_title = bp->BM; + if(brd_title[0] <= ' ') + brd_title = "�x�D��"; + sprintf(currBM, "�O�D�G%s", brd_title); + brd_title = ((bp->bvote != 2 && bp->bvote) ? "���ݪO�i��벼��" : + bp->title + 7); + currmode = (currmode & (MODE_DIRTY | MODE_MENU)) | MODE_STARTED ; + + if (HAS_PERM(PERM_ALLBOARD) || is_BM(bp->BM)) + currmode = currmode | MODE_BOARD | MODE_POST; + else if(haspostperm(currboard)) + currmode |= MODE_POST; +} + +static void readtitle() { + showtitle(currBM, brd_title); + outs("[��]���} [��]�\\Ū [^P]�o���峹 [b]�Ƨѿ� [d]�R�� [z]��ذ� " + "[TAB]��K [h]elp\n\033[7m �s�� �� �� �@ �� �� �� �� �D" + " \033[m"); +} + +extern int brc_num; +extern int brc_list[]; +extern char currtitle[]; + +extern int Tagger(); + +static void readdoent(int num, fileheader_t *ent) { + int type; + char *mark, *title, color; + + type = brc_unread(ent->filename,brc_num,brc_list) ? '+' : ' '; + + if((currmode & MODE_BOARD) && (ent->filemode & FILE_DIGEST)) + type = (type == ' ') ? '*' : '#'; + else if(currmode & MODE_BOARD || HAS_PERM(PERM_LOGINOK)) { + if(ent->filemode & FILE_MARKED) + type = (type == ' ') ? 'm' : 'M'; + + else if (TagNum && !Tagger(atoi(ent->filename + 2), 0, TAG_NIN)) + type = 'D'; + + else if (ent->filemode & FILE_SOLVED) + type = 's'; + } + + title = subject(mark = ent->title); + if(title == mark) + color = '1', mark = "��"; + else + color = '3', mark = "R:"; + + if(title[47]) + strcpy(title + 44, " �K"); /* ��h�l�� string �屼 */ + + if(strncmp(currtitle, title, 40)) + prints("%6d %c %-7s%-13.12s%s %s\n", num, type, + ent->date, ent->owner, mark, title); + else + prints("%6d %c %-7s%-13.12s\033[1;3%cm%s %s\033[m\n", num, type, + ent->date, ent->owner, color, mark, title); +} + +extern char currfile[]; + +int cmpfilename(fileheader_t *fhdr) { + return (!strcmp(fhdr->filename, currfile)); +} + +extern unsigned char currfmode; + +int cmpfmode(fileheader_t *fhdr) { + return (fhdr->filemode & currfmode); +} + +extern char currowner[]; + +int cmpfowner(fileheader_t *fhdr) { + return !strcasecmp(fhdr->owner, currowner); +} + +extern char *err_bid; +extern userinfo_t *currutmp; + +int whereami(int ent, fileheader_t *fhdr, char *direct) { + boardheader_t *bh, *p[32], *root; + int i,j; + + if(!currutmp->brc_id) return 0; + + move(1,0); + clrtobot(); + bh=getbcache(currutmp->brc_id); + root=getbcache(1); + p[0]=bh; + for(i=0;i<31 && p[i]->parent!=root && p[i]->parent;i++) + p[i+1]=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(int ent, fileheader_t *fhdr, char *direct) { + char bname[20]; + char bpath[60]; + boardheader_t *bh; + struct stat st; + int i; + + move(0, 0); + clrtoeol(); + make_blist(); + namecomplete(MSG_SELECT_BOARD, bname); + if(bname[0]=='\0' || !(i = getbnum(bname))) + return FULLUPDATE; + bh = getbcache(i); + if(!Ben_Perm(bh)) return FULLUPDATE; + strcpy(bname, bh->brdname); + currbid=i; + + setbpath(bpath, bname); + if((*bname == '\0') || (stat(bpath, &st) == -1)) { + move(2, 0); + clrtoeol(); + outs(err_bid); + return FULLUPDATE; + } + + currutmp->brc_id = currbid; + + brc_initial(bname); + set_board(); + setbdir(direct, currboard); + + move(1, 0); + clrtoeol(); + return NEWDIRECT; +} + +/* ----------------------------------------------------- */ +/* ��} innbbsd ��X�H��B�s�u��H���B�z�{�� */ +/* ----------------------------------------------------- */ +void outgo_post(fileheader_t *fh, char *board) { + FILE *foo; + + if((foo = fopen("innd/out.bntp", "a"))) { + fprintf(foo, "%s\t%s\t%s\t%s\t%s\n", board, + fh->filename, cuser.userid, cuser.username, fh->title); + fclose(foo); + } +} + +extern char *str_author1; +extern char *str_author2; + +static void cancelpost(fileheader_t *fh, int by_BM) { + FILE *fin, *fout; + char *ptr, *brd; + fileheader_t postfile; + char genbuf[200]; + char nick[STRLEN], fn1[STRLEN], fn2[STRLEN]; + + setbfile(fn1, currboard, fh->filename); + if((fin = fopen(fn1, "r"))) { + brd = by_BM ? "deleted" : "junk"; + + setbpath(fn2, brd); + stampfile(fn2, &postfile); + memcpy(postfile.owner, fh->owner, IDLEN + TTLEN + 10); + postfile.savemode = 'D'; + + if(fh->savemode == 'S') { + 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, '('))) + strcpy(nick, ptr + 1); + break; + } + } + + 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); + Rename(fn1, fn2); + setbdir(genbuf, brd); + append_record(genbuf, &postfile, sizeof(postfile)); + } +} + +extern char *str_reply; +extern char save_title[]; + +/* ----------------------------------------------------- */ +/* �o���B�^���B�s��B����峹 */ +/* ----------------------------------------------------- */ +void do_reply_title(int row, char *title) { + char genbuf[200]; + char genbuf2[4]; + + if(strncasecmp(title, str_reply, 4)) + sprintf(save_title, "Re: %s", title); + else + strcpy(save_title, title); + save_title[TTLEN - 1] = '\0'; + sprintf(genbuf, "�ĥέ���D�m%.60s�n��?[Y] ", save_title); + getdata(row, 0, genbuf, genbuf2, 4, LCECHO); + if(genbuf2[0] == 'n' || genbuf2[0] == 'N') + getdata(++row, 0, "���D�G", save_title, TTLEN, DOECHO); +} + +static void do_unanonymous_post(char* fpath) { + fileheader_t mhdr; + char title[128]; + char genbuf[200]; + + setbpath(genbuf, "UnAnonymous"); + if(dashd(genbuf)) { + stampfile(genbuf, &mhdr); + unlink(genbuf); + Link(fpath, genbuf); + strcpy(mhdr.owner, cuser.userid); + strcpy(mhdr.title, save_title); + mhdr.savemode = 0; + mhdr.filemode = 0; + setbdir(title, "UnAnonymous"); + append_record(title, &mhdr, sizeof(mhdr)); + } +} + +extern char quote_file[]; +extern char quote_user[]; +extern int curredit; +extern unsigned int currbrdattr; +extern char currdirect[]; +extern char *err_uid; + +#ifdef NO_WATER_POST +static time_t last_post_time = 0; +static time_t water_counts = 0; +#endif +int local_article; +char real_name[20]; + +static int do_general() { + fileheader_t postfile; + char fpath[80], buf[80]; + int aborted, defanony, ifuseanony; + char genbuf[200],*owner; + boardheader_t *bp; + int islocal; + + ifuseanony = 0; + bp = getbcache(currbid); + + clear(); + if(!(currmode & MODE_POST)) { + move(5, 10); + outs("�藍�_�A�z�ثe�L�k�b���o���峹�I"); + pressanykey(); + return FULLUPDATE; + } + +#ifdef NO_WATER_POST + /* �T�������̦h�o�����g�峹 */ + if(currutmp->lastact - last_post_time < 60 * 3) { + if(water_counts >= 5) { + move(5, 10); + outs("�藍�_�A�z���峹�Ӥ��o�A�h��Ҥ@�U�A�ݷ|�Apost�a�I"); + pressanykey(); + return FULLUPDATE; + } + } else { + last_post_time = currutmp->lastact; + water_counts = 0; + } +#endif + + setbfile(genbuf, currboard, FN_POST_NOTE ); + + if(more(genbuf,NA) == -1) + more("etc/"FN_POST_NOTE , NA); + + move(19,0); + prints("�o���峹��i\033[33m %s\033[m �j \033[32m%s\033[m �ݪO\n\n", + currboard, bp->title + 7); + + if(quote_file[0]) + do_reply_title(20, currtitle); + else { + getdata(21, 0, "���D�G", save_title, TTLEN, DOECHO); + strip_ansi(save_title,save_title,0); + } + if(save_title[0] == '\0') + return FULLUPDATE; + + curredit &= ~EDIT_MAIL; + curredit &= ~EDIT_ITEM; + setutmpmode(POSTING); + + /* ����� Internet �v���̡A�u��b�����o���峹 */ + if(HAS_PERM(PERM_INTERNET)) + local_article = 0; + else + local_article = 1; + + /* build filename */ + setbpath(fpath, currboard); + stampfile(fpath, &postfile); + + aborted = vedit(fpath, YEA, &islocal); + if(aborted == -1) { + unlink(fpath); + pressanykey(); + return FULLUPDATE; + } + water_counts++; /* po���\ */ + + /* 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 + /* �� */ + aborted = (aborted > MAX_POST_MONEY * 2) ? MAX_POST_MONEY : aborted / 2; + postfile.money = aborted; + strcpy(postfile.owner, owner); + strcpy(postfile.title, save_title); + if(islocal) { /* local save */ + postfile.savemode = 'L'; + postfile.filemode = FILE_LOCAL; + } else + postfile.savemode = 'S'; + + setbdir(buf, currboard); + if(append_record(buf, &postfile, sizeof(postfile)) != -1) { + setbtotal(currbid); + + if(currmode & MODE_SELECT) + append_record(currdirect,&postfile,sizeof(postfile)); + if(!islocal && !(bp->brdattr & BRD_NOTRAN)) + outgo_post(&postfile, currboard); + brc_addlist(postfile.filename); + + if(!(currbrdattr & BRD_HIDE) && + (!bp->level || (currbrdattr & BRD_POSTMASK))) { + setbpath(genbuf, ALLPOST); + stampfile(genbuf, &postfile); + unlink(genbuf); + + /* jochang: boards may spread across many disk */ + /* link doesn't work across device, + Link doesn't work if we have same-time-across-device posts, + we try symlink now */ + { + /* we need absolute path for symlink */ + char abspath[256]=BBSHOME"/"; + strcat(abspath,fpath); + symlink(abspath,genbuf); + } + strcpy(postfile.owner, owner); + strcpy(postfile.title, save_title); + postfile.savemode = 'L'; + setbdir(genbuf, ALLPOST); + if(append_record(genbuf, &postfile, sizeof(postfile)) != -1) { + setbtotal(getbnum(ALLPOST)); + } + } + + outs("���Q�K�X�G�i�A"); + +#ifdef MAX_POST_MONEY + aborted = (aborted > MAX_POST_MONEY) ? MAX_POST_MONEY : aborted; +#endif + if(strcmp(currboard, "Test") && !ifuseanony) { + prints("�o�O�z���� %d �g�峹�C �Z�S %d �ȡC", + ++cuser.numposts, aborted ); + demoney(aborted); + passwd_update(usernum, &cuser); /* post �� */ + } else + outs("���իH�C�J�����A�q�Х]�[�C"); + + /* �^�����@�̫H�c */ + + if(curredit & EDIT_BOTH) { + char *str, *msg = "�^���ܧ@�̫H�c"; + + if((str = strchr(quote_user, '.'))) { + if( +#ifndef USE_BSMTP + bbs_sendmail(fpath, save_title, str + 1) +#else + bsmtp(fpath, save_title, str + 1 ,0) +#endif + < 0) + msg = "�@�̵L�k���H"; + } else { + sethomepath(genbuf, quote_user); + stampfile(genbuf, &postfile); + unlink(genbuf); + Link(fpath, genbuf); + + strcpy(postfile.owner, cuser.userid); + strcpy(postfile.title, save_title); + postfile.savemode = 'B';/* both-reply flag */ + sethomedir(genbuf, quote_user); + if(append_record(genbuf, &postfile, sizeof(postfile)) == -1) + msg = err_uid; + } + outs(msg); + curredit ^= EDIT_BOTH; + } + if(currbrdattr & BRD_ANONYMOUS) + do_unanonymous_post(fpath); + } + pressanykey(); + return FULLUPDATE; +} + +int do_post() { + boardheader_t *bp; + bp = getbcache(currbid); + if(bp->brdattr & BRD_VOTEBOARD) + return do_voteboard(); + else if(!(bp->brdattr & BRD_GROUPBOARD)) + return do_general(); + touchdircache(currbid); + return 0; +} + +extern int b_lines; +extern int curredit; + +static void do_generalboardreply(fileheader_t *fhdr){ + char genbuf[200]; + getdata(b_lines - 1, 0, + "�� �^���� (F)�ݪO (M)�@�̫H�c (B)�G�̬ҬO (Q)�����H[F] ", + genbuf, 3, LCECHO); + switch(genbuf[0]) { + case 'm': + mail_reply(0, fhdr, 0); + case 'q': + break; + + case 'b': + curredit = EDIT_BOTH; + default: + strcpy(currtitle, fhdr->title); + strcpy(quote_user, fhdr->owner); + quote_file[79] = fhdr->savemode; + do_post(); + } + *quote_file = 0; +} + +int getindex(char *fpath, char *fname, int size) { + int fd, now=0; + fileheader_t fhdr; + + if((fd = open(fpath, O_RDONLY, 0)) != -1) { + while((read(fd, &fhdr, size) == size)) { + now++; + if(!strcmp(fhdr.filename,fname)) { + close(fd); + return now; + } + } + close(fd); + } + return 0; +} + +int invalid_brdname(char *brd) { + register char ch; + + ch = *brd++; + if(not_alnum(ch)) + return 1; + while((ch = *brd++)) { + if(not_alnum(ch) && ch != '_' && ch != '-' && ch != '.') + return 1; + } + return 0; +} + +static void do_reply(fileheader_t *fhdr) { + boardheader_t *bp; + bp = getbcache(currbid); + if (bp->brdattr & BRD_VOTEBOARD) + do_voteboardreply(fhdr); + else + do_generalboardreply(fhdr); +} + +static int reply_post(int ent, fileheader_t *fhdr, char *direct) { + if(!(currmode & MODE_POST)) + return DONOTHING; + + setdirpath(quote_file, direct, fhdr->filename); + do_reply(fhdr); + *quote_file = 0; + return FULLUPDATE; +} + +static int edit_post(int ent, fileheader_t *fhdr, char *direct) { + char fpath[80], fpath0[80]; + char genbuf[200]; + fileheader_t postfile; + boardheader_t *bp; + bp = getbcache(currbid); + if (!HAS_PERM(PERM_SYSOP) && (bp->brdattr & BRD_VOTEBOARD)) + return DONOTHING; + + if ((!HAS_PERM(PERM_SYSOP)) && + strcmp(fhdr->owner, cuser.userid)) + return DONOTHING; + setutmpmode(REEDIT); + setdirpath(genbuf, direct, fhdr->filename); + local_article = fhdr->filemode & FILE_LOCAL; + strcpy(save_title, fhdr->title); + +/* rocker.011018: �o�̬O���O���ˬd�@�U�ק�峹�᪺money�M�즳�����? */ + if(vedit(genbuf, 0, NULL) != -1) { + setbpath(fpath, currboard); + stampfile(fpath, &postfile); + unlink(fpath); + setbfile(fpath0, currboard, fhdr->filename); + + Rename(fpath0, fpath); + +/* rocker.011018: fix �걵�Ҧ���峹��峹�N������bug */ + if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) + { + fileheader_t hdr; + int num; + + num = fhdr->money & ~FHR_REFERENCE; + setbdir(fpath0, currboard); + get_record(fpath0, &hdr, sizeof (hdr), num); + + /* �A�o�̭ncheck�@�U��Ӫ�dir�̭��O���O���Q�H�ʹL... */ + if (!strcmp (hdr.filename, fhdr->filename)) + { + strcpy(hdr.filename, postfile.filename); + strcpy(hdr.title, save_title); + substitute_record(fpath0, &hdr, sizeof(hdr), num); + } + } + + strcpy(fhdr->filename, postfile.filename); + strcpy(fhdr->title, save_title); + brc_addlist(postfile.filename); + substitute_record(direct, fhdr, sizeof(*fhdr), ent); +/* rocker.011018: ���K��s�@�Ucache */ + touchdircache(currbid); + } + return FULLUPDATE; +} + +extern crosspost_t postrecord; +#define UPDATE_USEREC (currmode |= MODE_DIRTY) + +static int cross_post(int ent, fileheader_t *fhdr, 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]; + boardheader_t *bp; + make_blist(); + move(2, 0); + clrtoeol(); + move(3, 0); + clrtoeol(); + move(1, 0); + bp = getbcache(currbid); + if (bp && (bp->brdattr & BRD_VOTEBOARD)) + return FULLUPDATE; + namecomplete("������峹��ݪO�G", xboard); + if(*xboard == '\0' || !haspostperm(xboard)) + return FULLUPDATE; + + if((ent = str_checksum(fhdr->title)) != 0 && + ent == postrecord.checksum[0]) { + /* �ˬd cross post ���� */ + if(postrecord.times++ > MAX_CROSSNUM) + anticrosspost(); + } else { + postrecord.times = 0; + postrecord.checksum[0] = ent; + } + + ent = 1; + if(HAS_PERM(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) + sprintf(xtitle, "[���]%.66s", fhdr->title); + else + strcpy(xtitle, fhdr->title); + + sprintf(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)) + strcpy(xtitle, genbuf); + } + + 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) + strcpy(xfile.owner, fhdr->owner); + else + strcpy(xfile.owner, cuser.userid); + strcpy(xfile.title, xtitle); + if(genbuf[0] == 'l') { + xfile.savemode = 'L'; + xfile.filemode = FILE_LOCAL; + } else + xfile.savemode = 'S'; + + setbfile(fname, currboard, fhdr->filename); +// if(ent) { + xptr = fopen(xfpath, "w"); + + strcpy(save_title, xfile.title); + strcpy(xfpath, currboard); + strcpy(currboard, xboard); + write_header(xptr); + strcpy(currboard, xfpath); + + fprintf(xptr, "�� [��������� %s �ݪO]\n\n", currboard); + + b_suckinfile(xptr, fname); + addsignature(xptr,0); + fclose(xptr); +/* Cross fs�����D + } else { + unlink(xfpath); + link(fname, xfpath); + } +*/ + setbdir(fname, xboard); + append_record(fname, &xfile, sizeof(xfile)); + bp = getbcache(getbnum(xboard)); + if(!xfile.filemode && !(bp->brdattr && BRD_NOTRAN)) + outgo_post(&xfile, xboard); + setbtotal(getbnum(xboard)); + cuser.numposts++; + UPDATE_USEREC; + outs("�峹�������"); + pressanykey(); + currmode = currmode0; + } + return FULLUPDATE; +} + +static int read_post(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[200]; + int more_result; + + if(fhdr->owner[0] == '-') + return DONOTHING; + + setdirpath(genbuf, direct, fhdr->filename); + + if((more_result = more(genbuf, YEA)) == -1) + return DONOTHING; + + brc_addlist(fhdr->filename); + strncpy(currtitle, subject(fhdr->title), 40); + strncpy(currowner, subject(fhdr->owner), IDLEN + 2); + + switch (more_result) { + case 1: + return READ_PREV; + case 2: + return RELATE_PREV; + case 3: + return READ_NEXT; + case 4: + return RELATE_NEXT; + case 5: + return RELATE_FIRST; + case 6: + return FULLUPDATE; + case 7: + case 8: + if((currmode & MODE_POST)) { + strcpy(quote_file, genbuf); + do_reply(fhdr); + *quote_file = 0; + } + return FULLUPDATE; + case 9: + return 'A'; + case 10: + return 'a'; + case 11: + return '/'; + case 12: + return '?'; + } + + + outmsg("\033[34;46m �\\Ū�峹 \033[31;47m (R/Y)\033[30m�^�H \033[31m" + "(=[]<>)\033[30m�����D�D \033[31m(����)\033[30m�W�U�� \033[31m(��)" + "\033[30m���} \033[m"); + + switch(egetch()) { + case 'q': + case 'Q': + case KEY_LEFT: + break; + + case ' ': + case KEY_RIGHT: + case KEY_DOWN: + case KEY_PGDN: + case 'n': + case Ctrl('N'): + return READ_NEXT; + + case KEY_UP: + case 'p': + case Ctrl('P'): + case KEY_PGUP: + return READ_PREV; + + case '=': + return RELATE_FIRST; + + case ']': + case 't': + return RELATE_NEXT; + + case '[': + return RELATE_PREV; + + case '.': + case '>': + return THREAD_NEXT; + + case ',': + case '<': + return THREAD_PREV; + + case Ctrl('C'): + cal(); + return FULLUPDATE; + break; + + case Ctrl('I'): + t_idle(); + return FULLUPDATE; + case 'y': + case 'r': + case 'R': + case 'Y': + if((currmode & MODE_POST)) { + strcpy(quote_file, genbuf); + do_reply(fhdr); + *quote_file = 0; + } + } + return FULLUPDATE; +} + +/* ----------------------------------------------------- */ +/* �Ķ���ذ� */ +/* ----------------------------------------------------- */ +static int b_man() { + char buf[64]; + + setapath(buf, currboard); + if( (currmode & MODE_BOARD) || HAS_PERM(PERM_SYSOP) ){ + char genbuf[128]; + int fd; + sprintf(genbuf, "%s/.rebuild", buf); + if( (fd = open(genbuf, O_CREAT, 0640)) > 0 ) + close(fd); + } + return a_menu(currboard, buf, HAS_PERM(PERM_ALLBOARD) ? 2 : + (currmode & MODE_BOARD ? 1 : 0)); +} + +#ifndef NO_GAMBLE +static int join_gamble(int ent, fileheader_t *fhdr, char *direct) { + ticket(currbid); + return FULLUPDATE; +} +static int hold_gamble(int ent, fileheader_t *fhdr, char *direct) { + char fn_ticket[128],fn_ticket_end[128],genbuf[128], + msg[256]="",yn[10]=""; + int i; + FILE *fp=NULL; + + if(!(currmode & MODE_BOARD)) return 0; + setbfile(fn_ticket, currboard, FN_TICKET); + setbfile(fn_ticket_end, currboard, FN_TICKET_END); + 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); + return FULLUPDATE; + } + + if(dashf(fn_ticket_end)) + { + getdata(b_lines - 1, 0, "�w�g���|���L, " + "�O�_�n [�}��]?(N/y)�G", yn, 3, LCECHO); + if(yn[0]!='y') return FULLUPDATE; + openticket(currbid); + 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(genbuf, currboard, FN_TICKET_ITEMS); + +// sprintf(genbuf, "%s/"FN_TICKET_ITEMS, direct); + + if(!(fp=fopen(genbuf,"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); + move(3,0); + sprintf(genbuf,"�Ш� %s �� ��'f'�ѻP���!\n\n�@�i %d Ptt��, �o�O%s�����\n", + currboard, + i, i<100 ? "�p�䦡" : i<500 ? "������": + i<1000 ?"�Q�گ�" : i<5000 ?"�I����" : "�ɮa����"); + strcat(msg, genbuf); + prints("�Ш̦���J�m���W��, �ݴ���2~8��. (�����K��, ��J������enter)\n"); + for(i=0; i<8; i++) + { + sprintf(yn, " %d)",i+1); + getdata(6+i, 0, yn, genbuf, 9, DOECHO); + if(!genbuf[0] && i>1) + break; + fprintf(fp,"%s\n",genbuf); + } + fclose(fp); + move(8+i,0); + prints("��L�]�w����"); + sprintf(genbuf,"[���i] %s �� �}�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�� + + return FULLUPDATE; +} +#endif + +static int cite_post(int ent, fileheader_t *fhdr, char *direct) { + char fpath[256]; + char title[TTLEN + 1]; + + setbfile(fpath, currboard, fhdr->filename); + strcpy(title, "�� "); + strncpy(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, char *direct) { + char genbuf[200]; + fileheader_t tmpfhdr = *fhdr; + int dirty = 0; + + if(currmode & MODE_BOARD || !strcmp(cuser.userid,fhdr->owner)) { + if(getdata(b_lines - 1, 0, "���D�G", genbuf, TTLEN, DOECHO)) { + strcpy(tmpfhdr.title, genbuf); + dirty++; + } + } + + if(HAS_PERM(PERM_SYSOP)) { + if(getdata(b_lines - 1, 0, "�@�̡G", genbuf, IDLEN + 2, DOECHO)) { + strcpy(tmpfhdr.owner, genbuf); + dirty++; + } + + if(getdata(b_lines - 1, 0, "����G", genbuf, 6, DOECHO)) { + sprintf(tmpfhdr.date, "%.5s", genbuf); + dirty++; + } + } + + if(currmode & MODE_BOARD || !strcmp(cuser.userid,fhdr->owner)) { + getdata(b_lines-1, 0, "�T�w(Y/N)?[n] ", genbuf, 3, DOECHO); + if((genbuf[0] == 'y' || genbuf[0] == 'Y') && dirty) { + *fhdr = tmpfhdr; + substitute_record(direct, fhdr, sizeof(*fhdr), ent); +/* rocker.011018: �o�����ӧ令��reference���覡���o��Ӫ��ɮ� */ +#if 0 + if((currmode & MODE_SELECT)) { + int now; + + setbdir(genbuf, currboard); + now = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + substitute_record(genbuf, fhdr, sizeof(*fhdr), now); + } +#else + if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) + { + fileheader_t hdr; + int num; + + num = fhdr->money & ~FHR_REFERENCE; + setbdir(genbuf, currboard); + get_record(genbuf, &hdr, sizeof (hdr), num); + + /* �A�o�̭ncheck�@�U��Ӫ�dir�̭��O���O���Q�H�ʹL... */ + if (strcmp (hdr.filename, fhdr->filename)) + num = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + + substitute_record(genbuf, fhdr, sizeof(*fhdr), num); + } +#endif + touchdircache(currbid); + } + return FULLUPDATE; + } + return DONOTHING; +} + +extern unsigned int currstat; + +static int solve_post(int ent, fileheader_t * fhdr, char *direct){ + if (HAS_PERM(PERM_SYSOP)) { + fhdr->filemode ^= FILE_SOLVED; + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + touchdircache(currbid); + return PART_REDRAW; + } + return DONOTHING; +} + +static int mark_post(int ent, fileheader_t *fhdr, char *direct) { + + if(!(currmode & MODE_BOARD)) return DONOTHING; + + fhdr->filemode ^= FILE_MARKED; + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + + /* rocker.011018: �걵�Ҧ���reference�W�i�IJv */ + if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) + { + fileheader_t hdr; + char genbuf[100]; + int num; + + num = fhdr->money & ~FHR_REFERENCE; + setbdir(genbuf, currboard); + get_record(genbuf, &hdr, sizeof (hdr), num); + + /* �A�o�̭ncheck�@�U��Ӫ�dir�̭��O���O���Q�H�ʹL... */ + if (strcmp (hdr.filename, fhdr->filename)) + num = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + + substitute_record(genbuf, fhdr, sizeof(*fhdr), num); + } + touchdircache(currbid); + return PART_REDRAW; +} + +extern char *msg_sure_ny; + +int del_range(int ent, fileheader_t *fhdr, char *direct) { + char num1[8], num2[8]; + int inum1, inum2; + +/* rocker.011018: �걵�Ҧ��U�٬O�����\�R������n */ + if(currmode & MODE_SELECT) { + outmsg("�Х��^�쥿�`�Ҧ���A�i��R��..."); + refresh(); + /*safe_sleep(1);*/ + return FULLUPDATE; + } + + if((currstat != READING) || (currmode & MODE_BOARD)) { + getdata(1, 0, "[�]�w�R���d��] �_�I�G", num1, 5, DOECHO); + inum1 = atoi(num1); + if(inum1 <= 0) { + outmsg("�_�I���~"); + refresh(); + /*safe_sleep(1);*/ + return FULLUPDATE; + } + getdata(1, 28, "���I�G", num2, 5, DOECHO); + inum2 = atoi(num2); + if(inum2 < inum1) { + outmsg("���I���~"); + refresh(); + /*safe_sleep(1);*/ + return FULLUPDATE; + } + getdata(1, 48, msg_sure_ny, num1, 3, LCECHO); + if(*num1 == 'y') { + outmsg("�B�z��,�еy��..."); + refresh(); + if(currmode & MODE_SELECT) { + int fd,size = sizeof(fileheader_t); + char genbuf[100]; + fileheader_t rsfh; + int i = inum1,now; + if(currstat == RMAIL) + sethomedir(genbuf, cuser.userid); + else + setbdir(genbuf,currboard); + if((fd = (open(direct, O_RDONLY, 0))) != -1) { + if(lseek(fd, (off_t)(size * (inum1 - 1)), SEEK_SET) != + -1) { + while(read(fd,&rsfh,size) == size) { + if(i > inum2) + break; + now = getindex(genbuf, rsfh.filename, size); + strcpy(currfile, rsfh.filename); + delete_file(genbuf, sizeof(fileheader_t), now, + cmpfilename); + i++; + } + } + close(fd); + } + } + + delete_range(direct, inum1, inum2); + fixkeep(direct, inum1); + + if(currmode & MODE_BOARD) + setbtotal(currbid); + + return DIRCHANGED; + } + return FULLUPDATE; + } + return DONOTHING; +} + +extern char *msg_del_ny; +extern char *msg_del_ok; + +static int del_post(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[100]; + int not_owned; + boardheader_t *bp; + + bp = getbcache(currbid); + + if((fhdr->filemode & FILE_MARKED) || (fhdr->filemode & FILE_DIGEST) || + (fhdr->owner[0] == '-')) + return DONOTHING; + + not_owned = strcmp(fhdr->owner, cuser.userid); + if((!(currmode & MODE_BOARD) && not_owned) || + ((bp->brdattr & BRD_VOTEBOARD) && !HAS_PERM(PERM_SYSOP)) || + !strcmp(cuser.userid, STR_GUEST)) + return DONOTHING; + + getdata(1, 0, msg_del_ny, genbuf, 3, LCECHO); + if(genbuf[0] == 'y' || genbuf[0] == 'Y') { + strcpy(currfile, fhdr->filename); + + setbfile(genbuf,currboard,fhdr->filename); + if(!delete_file (direct, sizeof(fileheader_t), ent, cmpfilename)) { + + if(currmode & MODE_SELECT) + { + /* rocker.011018: �Q��reference��Cloading */ + fileheader_t hdr; + int num; + + num = fhdr->money & ~FHR_REFERENCE; + setbdir(genbuf, currboard); + get_record(genbuf, &hdr, sizeof (hdr), num); + + /* �A�o�̭ncheck�@�U��Ӫ�dir�̭��O���O���Q�H�ʹL... */ + if (strcmp (hdr.filename, fhdr->filename)) + { + num=getindex(genbuf,fhdr->filename,sizeof(fileheader_t)); + get_record(genbuf, &hdr, sizeof (hdr), num); + } + + /* rocker.011018: �o�̭n�٭�Q�}�a��money */ + fhdr->money = hdr.money; + delete_file (genbuf, sizeof(fileheader_t), num, cmpfilename); + } + +#if 0 + { + setbdir(genbuf,currboard); + now=getindex(genbuf,fhdr->filename,sizeof(fileheader_t)); + delete_file (genbuf, sizeof(fileheader_t),now,cmpfilename); + } +#endif + cancelpost(fhdr, not_owned); + + setbtotal(currbid); + if (fhdr->money < 0) + fhdr->money = 0; + if (not_owned && strcmp(currboard, "Test")){ + deumoney(searchuser(fhdr->owner), -fhdr->money); + } + if(!not_owned && strcmp(currboard, "Test")) { + if(cuser.numposts) + cuser.numposts--; + move(b_lines - 1, 0); + clrtoeol(); + demoney(-fhdr->money); + passwd_update(usernum, &cuser); /* post �� */ + prints("%s�A�z���峹� %d �g�A��I�M��O %d ��", msg_del_ok, + cuser.numposts,fhdr->money); + refresh(); + pressanykey(); + } + return DIRCHANGED; + } + } + return FULLUPDATE; +} + +static int view_postmoney(int ent, fileheader_t *fhdr, char *direct) { + move(b_lines - 1, 0); + clrtoeol(); + prints("�o�@�g�峹�� %d ��", fhdr->money); + refresh(); + pressanykey(); + return FULLUPDATE; +} + +#ifdef OUTJOBSPOOL +/* �ݪ��ƥ� */ +static int tar_addqueue(int ent, fileheader_t *fhdr, char *direct) { + char email[60], qfn[80], ans[2]; + FILE *fp; + char bakboard, bakman; + clear(); + showtitle("�ݪ��ƥ�", BBSNAME); + move(2, 0); + if( !((currmode & MODE_BOARD) || HAS_PERM(PERM_SYSOP)) ) { + move(5, 10); + outs("�p�n�O���D�άO�����~������� -.-\"\""); + pressanykey(); + return FULLUPDATE; + } + + sprintf(qfn, BBSHOME "/jobspool/tarqueue.%s", currboard); + if( access(qfn, 0) == 0 ){ + outs("�w�g�Ʃw��{, �y��|�i��ƥ�"); + pressanykey(); + return FULLUPDATE; + } + 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; + } + + getdata(6, 0, "�n�ƥ��ݪ����e��(Y/N)?[Y]", ans, 2, LCECHO); + bakboard = (ans[0] == 'n' || ans[0] =='N') ? 0 : 1; + getdata(7, 0, "�n�ƥ���ذϤ��e��(Y/N)?[N]", ans, 2, LCECHO); + bakman = (ans[0] == 'y' || ans[0] =='Y') ? 1 : 0; + if( !bakboard && !bakman ){ + move(8, 0); + outs("�i�O�ڭ̥u��ƥ��ݪ��κ�ذϪ��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 + +static int sequent_ent; +static int continue_flag; + +/* ----------------------------------------------------- */ +/* �̧�Ū�s�峹 */ +/* ----------------------------------------------------- */ +static int sequent_messages(fileheader_t *fptr) { + static int idc; + char genbuf[200]; + + if(fptr == NULL) + return (idc = 0); + + if(++idc < sequent_ent) + return 0; + + if(!brc_unread(fptr->filename,brc_num,brc_list)) + return 0; + + if(continue_flag) + genbuf[0] = 'y'; + else { + prints("Ū���峹��G[%s] �@�̡G[%s]\n���D�G[%s]", + currboard, fptr->owner, fptr->title); + getdata(3, 0, "(Y/N/Quit) [Y]: ", genbuf, 3, LCECHO); + } + + if(genbuf[0] != 'y' && genbuf[0]) { + clear(); + return (genbuf[0] == 'q' ? QUIT : 0); + } + + setbfile(genbuf, currboard, fptr->filename); + brc_addlist(fptr->filename); + + if(more(genbuf, YEA) == 0) + outmsg("\033[31;47m \033[31m(R)\033[30m�^�H \033[31m(��,n)" + "\033[30m�U�@�� \033[31m(��,q)\033[30m���} \033[m"); + continue_flag = 0; + + switch(egetch()) { + case KEY_LEFT: + case 'e': + case 'q': + case 'Q': + break; + + case 'y': + case 'r': + case 'Y': + case 'R': + if(currmode & MODE_POST) { + strcpy(quote_file, genbuf); + do_reply(fptr); + *quote_file = 0; + } + break; + + case ' ': + case KEY_DOWN: + case '\n': + case 'n': + continue_flag = 1; + } + + clear(); + return 0; +} + +static int sequential_read(int ent, fileheader_t *fhdr, char *direct) { + char buf[40]; + + clear(); + sequent_messages((fileheader_t *) NULL); + sequent_ent = ent; + continue_flag = 0; + setbdir(buf, currboard); + apply_record(buf, sequent_messages, sizeof(fileheader_t)); + return FULLUPDATE; +} + +extern char *fn_notes; +extern char *msg_cancel; +extern char *fn_board; + +/* ----------------------------------------------------- */ +/* �ݪO�Ƨѿ��B��K�B��ذ� */ +/* ----------------------------------------------------- */ +int b_note_edit_bname(int bid) { + char buf[64]; + int aborted; + boardheader_t *fh=getbcache(bid); + + setbfile(buf, fh->brdname, fn_notes); + aborted = vedit(buf, NA, NULL); + if(aborted == -1) { + clear(); + outs(msg_cancel); + pressanykey(); + } else { + aborted = (fh->bupdate - time(0)) / 86400 + 1; + sprintf(buf,"%d", aborted > 0 ? aborted : 0); + getdata_buf(3, 0, "�г]�w���Ĵ���(0 - 9999)�ѡH", buf, 5, DOECHO); + aborted = atoi(buf); + fh->bupdate = aborted ? time(0) + aborted * 86400 : 0; + substitute_record(fn_board, fh, sizeof(boardheader_t), bid); + } + return 0; +} + +static int b_notes_edit() { + if(currmode & MODE_BOARD) { + b_note_edit_bname(currbid); + return FULLUPDATE; + } + return 0; +} + +static int b_water_edit() { + if(currmode & MODE_BOARD) { + friend_edit(BOARD_WATER); + return FULLUPDATE; + } + return 0; +} + +static int visable_list_edit() { + if(currmode & MODE_BOARD) { + friend_edit(BOARD_VISABLE); + hbflreload(currbid); + return FULLUPDATE; + } + return 0; +} + +static int b_post_note() { + char buf[200], yn[3]; + + if(currmode & MODE_BOARD) { + setbfile(buf, currboard, FN_POST_NOTE ); + if(more(buf,NA) == -1) more("etc/"FN_POST_NOTE , NA); + getdata(b_lines - 2, 0, "�O�_�n�Φۭqpost�`�N�ƶ�?", yn, 3, LCECHO); + if(yn[0] == 'y') + vedit(buf, NA, NULL); + else + unlink(buf); + return FULLUPDATE; + } + return 0; +} + +static int b_application() { + char buf[200]; + + if(currmode & MODE_BOARD) { + setbfile(buf, currboard, FN_APPLICATION); + vedit(buf, NA, NULL); + return FULLUPDATE; + } + return 0; +} + +static int can_vote_edit() { + if(currmode & MODE_BOARD) { + friend_edit(FRIEND_CANVOTE); + return FULLUPDATE; + } + return 0; +} + +static int bh_title_edit() { + boardheader_t *bp; + + if(currmode & MODE_BOARD) { + char genbuf[BTLEN]; + + 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,0); + strcpy(bp->title + 7,genbuf); + substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); + log_usies("SetBoard", currboard); + return FULLUPDATE; + } + return 0; +} + +static int b_notes() { + char buf[64]; + + setbfile(buf, currboard, fn_notes); + if(more(buf, NA) == -1) { + clear(); + move(4, 20); + outs("���ݪO�|�L�u�Ƨѿ��v�C"); + } + pressanykey(); + return FULLUPDATE; +} + +int board_select() { + char fpath[80]; + char genbuf[100]; + + currmode &= ~MODE_SELECT; + sprintf(fpath, "SR.%s", cuser.userid); + setbfile(genbuf, currboard, fpath); + unlink(genbuf); + if(currstat == RMAIL) + sethomedir(currdirect, cuser.userid); + else + setbdir(currdirect, currboard); + return NEWDIRECT; +} + +int board_digest() { + if(currmode & MODE_SELECT) + board_select(); + currmode ^= MODE_DIGEST; + if(currmode & MODE_DIGEST) + currmode &= ~MODE_POST; + else if (haspostperm(currboard)) + currmode |= MODE_POST; + + setbdir(currdirect, currboard); + return NEWDIRECT; +} + +int board_etc() { + if(!HAS_PERM(PERM_SYSOP)) + return DONOTHING; + currmode ^= MODE_ETC; + if(currmode & MODE_ETC) + currmode &= ~MODE_POST; + else if(haspostperm(currboard)) + currmode |= MODE_POST; + + setbdir(currdirect, currboard); + return NEWDIRECT; +} + +extern char *fn_mandex; + +static int good_post(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[200]; + char genbuf2[200]; + int delta = 0; + + if((currmode & MODE_DIGEST) || !(currmode & MODE_BOARD)) + return DONOTHING; + + if(fhdr->filemode & FILE_DIGEST) { + fhdr->filemode = (fhdr->filemode & ~FILE_DIGEST); + if(!strcmp(currboard,"Note") || !strcmp(currboard,"PttBug") || + !strcmp(currboard,"Artdsn") || !strcmp(currboard, "PttLaw")) { + deumoney(searchuser(fhdr->owner),-1000); + if(!(currmode & MODE_SELECT)) + fhdr->money -= 1000; + else + delta = -1000; + } + } else { + fileheader_t digest; + char *ptr, buf[64]; + + memcpy(&digest, fhdr, sizeof(digest)); + digest.filename[0] = 'G'; + strcpy(buf, direct); + ptr = strrchr(buf, '/') + 1; + ptr[0] = '\0'; + sprintf(genbuf, "%s%s", buf, digest.filename); + + if(dashf(genbuf)) unlink (genbuf); + + digest.savemode = digest.filemode = 0; + sprintf(genbuf2, "%s%s", buf, fhdr->filename); + Link(genbuf2, genbuf); + strcpy(ptr, fn_mandex); + append_record(buf, &digest, sizeof(digest)); + + fhdr->filemode = (fhdr->filemode & ~FILE_MARKED) | FILE_DIGEST; + if(!strcmp(currboard, "Note") || !strcmp(currboard, "PttBug") || + !strcmp(currboard,"Artdsn") || !strcmp(currboard, "PttLaw")) { + deumoney(searchuser(fhdr->owner), 1000); + if(!(currmode & MODE_SELECT)) fhdr->money += 1000; + else delta = 1000; + } + } + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + touchdircache(currbid); +/* rocker.011018: �걵�Ҧ���reference�W�i�IJv */ + if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) + { + fileheader_t hdr; + char genbuf[100]; + int num; + + num = fhdr->money & ~FHR_REFERENCE; + setbdir(genbuf, currboard); + get_record(genbuf, &hdr, sizeof (hdr), num); + + /* �A�o�̭ncheck�@�U��Ӫ�dir�̭��O���O���Q�H�ʹL... */ + if (strcmp (hdr.filename, fhdr->filename)) + { + num = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + get_record(genbuf, &hdr, sizeof (hdr), num); + } + fhdr->money = hdr.money + delta; + + substitute_record(genbuf, fhdr, sizeof(*fhdr), num); + } +#if 0 + if(currmode & MODE_SELECT) { + int now; + char genbuf[100]; + + setbdir(genbuf, currboard); + now=getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + substitute_record(genbuf, fhdr, sizeof(*fhdr), now); + } +#endif + return PART_REDRAW; +} + +/* help for board reading */ +static char *board_help[] = { + "\0���\\��ݪO�ާ@����", + "\01�R�O", + "(p)(��) �W���@�g�峹 (^P) �o���峹", + "(n)(��) �U���@�g�峹 (d) �R���峹", + "(P)(PgUp) �W���@�� (S) ��s�����峹", + "(N)(PgDn) �U���@�� (##) ���� ## ���峹", + "(r)(��) �\\Ū���g�峹 ($) ����̫�@�g�峹", + "\01�i���R�O", + "(tab)/z ��K�Ҧ�/��ذ� (a)(A) ��M�@��", + "(b/f) �iŪ�Ƨѿ�/�ѻP��L (?)(/) ��M���D", + "(V/R) �벼/�d�ߧ벼���G (^W) �ڦb���̥i�ݨ�ݪO������", + "(x) ����峹���L�ݪO (=)/([]<>-+) ��M���g�峹/�D�D���\\Ū", +#ifdef INTERNET_EMAIL + "(F) �峹�H�^Internet�l�c (U) �N�峹 uuencode ��H�^�l�c", +#endif + "(E) ���s�峹 (^H) �C�X�Ҧ��� New Post(s)", + "\01�O�D�R�O", + "(G) �|���L/����U�`/�}��(W/w/v) �s��Ƨѿ�/�����W��/�i�ݨ��W��", + "(M/o) �|��벼/�s�p�벼�W�� (m/c/g) �O�d�峹/������/��K", + "(D) �R���@�q�d�峹 (T/B) ���s�峹���D/���s�ݪ����D", + "(i) �s��ӽФJ�|���� (t/^D) �аO�峹/�尣�аO���峹", + "(O) �s��Post�`�N�ƶ� (H) �ݪO����/�{��", + NULL +}; + +static int b_help() { + show_help(board_help); + return FULLUPDATE; +} + +/* ----------------------------------------------------- */ +/* �O�D�]�w����/ ������ */ +/* ----------------------------------------------------- */ +char board_hidden_status; +#ifdef BMCHS +extern char *fn_board; +static int change_hidden(int ent, fileheader_t *fhdr, char *direct) +{ + boardheader_t bh; + int bid; + char ans[4]; + + if( !((currmode & MODE_BOARD) || HAS_PERM(PERM_SYSOP)) || + currboard[0] == 0 || + (bid = getbnum(currboard)) < 0 || + get_record(fn_board, &bh, sizeof(bh), bid) == -1 ) + return DONOTHING; + + if( ((bh.brdattr & BRD_HIDE) && (bh.brdattr & BRD_POSTMASK)) ){ + getdata(1, 0, "�ثe�O�b���Ϊ��A, �n�����ι�(Y/N)?[N]", ans, 2, LCECHO); + if( ans[0] != 'y' && ans[0] != 'Y' ) + return FULLUPDATE; + getdata(2, 0, "�A�T�{�@��, �u���n��O�O���}�� @____@(Y/N)?[N]", + ans, 2, LCECHO); + if( ans[0] != 'y' && ans[0] != 'Y' ) + return FULLUPDATE; + if( bh.brdattr & BRD_HIDE ) bh.brdattr -= BRD_HIDE; + if( bh.brdattr & BRD_POSTMASK ) bh.brdattr -= BRD_POSTMASK; + log_usies("OpenBoard", bh.brdname); + outs("�g�ߤ��Dz��H�A�L�B���D���q�C\n"); + board_hidden_status = 0; + hbflreload(bid); + } + else{ + getdata(1, 0, "�ثe�O�b�{�Ϊ��A, �n���ι�(Y/N)?[N]", ans, 2, LCECHO); + if( ans[0] != 'y' && ans[0] != 'Y' ) + return FULLUPDATE; + bh.brdattr |= BRD_HIDE; + bh.brdattr |= BRD_POSTMASK; + log_usies("CloseBoard", bh.brdname); + outs("�g�ߤ��w�����A���ߵ��۬í��C\n"); + board_hidden_status = 1; + } + setup_man(&bh); + substitute_record(fn_board, &bh, sizeof(bh), bid); + reset_board(bid); + log_usies("SetBoard", bh.brdname); + pressanykey(); + return FULLUPDATE; +} +#endif + +/* ----------------------------------------------------- */ +/* �ݪO�\��� */ +/* ----------------------------------------------------- */ +struct onekey_t read_comms[] = { + {KEY_TAB, board_digest}, + {'C', board_etc}, + {'b', b_notes}, + {'c', cite_post}, + {'r', read_post}, + {'z', b_man}, + {'D', del_range}, + {'S', sequential_read}, + {'E', edit_post}, + {'T', edit_title}, + {'s', do_select}, + {'R', b_results}, + {'V', b_vote}, + {'M', b_vote_maintain}, + {'B', bh_title_edit}, + {'W', b_notes_edit}, + {'O', b_post_note}, + {'w', b_water_edit}, + {'v', visable_list_edit}, + {'i', b_application}, + {'o', can_vote_edit}, + {'x', cross_post}, + {'h', b_help}, +#ifndef NO_GAMBLE + {'f', join_gamble}, + {'G', hold_gamble}, +#endif + {'g', good_post}, + {'y', reply_post}, + {'d', del_post}, + {'m', mark_post}, + {'L', solve_post}, + {Ctrl('P'), do_post}, + {Ctrl('W'), whereami}, + {'Q', view_postmoney}, +#ifdef OUTJOBSPOOL + {'u', tar_addqueue}, +#endif +#ifdef BMCHS + {'H', change_hidden}, +#endif + {'\0', NULL} +}; + +time_t board_visit_time; + +int Read() { + int mode0 = currutmp->mode; + int stat0 = currstat, tmpbid=currutmp->brc_id; + char buf[40]; +#ifdef LOG_BOARD + time_t usetime = time(0); +#endif + + setutmpmode(READING); + set_board(); + + if(board_visit_time < board_note_time) { + setbfile(buf, currboard, fn_notes); + more(buf, NA); + pressanykey(); + } + currutmp->brc_id = currbid; + setbdir(buf, currboard); + curredit &= ~EDIT_MAIL; + i_read(READING, buf, readtitle, readdoent, read_comms, + currbid); +#ifdef LOG_BOARD + log_board(currboard, time(0) - usetime); +#endif + brc_update(); + + currutmp->brc_id =tmpbid; + currutmp->mode = mode0; + currstat = stat0; + return 0; +} + +void ReadSelect() { + int mode0 = currutmp->mode; + int stat0 = currstat; + char genbuf[200]; + + currstat = XMODE; + if(do_select(0, 0, genbuf) == NEWDIRECT) + Read(); + currutmp->brc_id=0; + currutmp->mode = mode0; + currstat = stat0; +} + +#ifdef LOG_BOARD +static void log_board(char *mode, time_t usetime) { + time_t now; + char buf[ 256 ]; + + if(usetime > 30) { + now = time(0); + sprintf(buf, "USE %-20.20s Stay: %5ld (%s) %s", + mode, usetime ,cuser.userid ,ctime(&now)); + log_file(FN_USEBOARD,buf); + } +} +#endif + +int Select() { + char genbuf[200]; + + setutmpmode(SELECT); + do_select(0, NULL, genbuf); + return 0; +} diff --git a/mbbsd/board.c b/mbbsd/board.c new file mode 100644 index 00000000..44b4b842 --- /dev/null +++ b/mbbsd/board.c @@ -0,0 +1,1098 @@ +/* $Id: board.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "modes.h" +#include "common.h" +#include "proto.h" + +#define BRC_STRLEN 15 /* Length of board name */ +#define BRC_MAXSIZE 24576 +#define BRC_ITEMSIZE (BRC_STRLEN + 1 + BRC_MAXNUM * sizeof( int )) +#define BRC_MAXNUM 80 + +extern userinfo_t *currutmp; +static char *brc_getrecord(char *ptr, char *name, int *pnum, int *list) { + int num; + char *tmp; + + strncpy(name, ptr, BRC_STRLEN); + ptr += BRC_STRLEN; + num = (*ptr++) & 0xff; + tmp = ptr + num * sizeof(int); + if (num > BRC_MAXNUM) + num = BRC_MAXNUM; + *pnum = num; + memcpy(list, ptr, num * sizeof(int)); + return tmp; +} + +static time_t brc_expire_time; + +static char *brc_putrecord(char *ptr, char *name, int num, int *list) { + if(num > 0 && list[0] > brc_expire_time) { + if (num > BRC_MAXNUM) + num = BRC_MAXNUM; + + while(num > 1 && list[num - 1] < brc_expire_time) + num--; + + strncpy(ptr, name, BRC_STRLEN); + ptr += BRC_STRLEN; + *ptr++ = num; + memcpy(ptr, list, num * sizeof(int)); + ptr += num * sizeof(int); + } + return ptr; +} + +extern userec_t cuser; +extern char currboard[]; /* name of currently selected board */ +static int brc_changed = 0; +static char brc_buf[BRC_MAXSIZE]; +int brc_num; +static char brc_name[BRC_STRLEN]; +int brc_list[BRC_MAXNUM]; +static char *fn_boardrc = ".boardrc"; +static int brc_size; + +void brc_update() { + if(brc_changed && cuser.userlevel) { + char dirfile[STRLEN], *ptr; + char tmp_buf[BRC_MAXSIZE - BRC_ITEMSIZE], *tmp; + char tmp_name[BRC_STRLEN]; + int tmp_list[BRC_MAXNUM], tmp_num; + int fd, tmp_size; + + ptr = brc_buf; + if(brc_num > 0) + ptr = brc_putrecord(ptr, brc_name, brc_num, brc_list); + + setuserfile(dirfile, fn_boardrc); + if((fd = open(dirfile, O_RDONLY)) != -1) { + tmp_size = read(fd, tmp_buf, sizeof(tmp_buf)); + close(fd); + } else { + tmp_size = 0; + } + + tmp = tmp_buf; + while(tmp < &tmp_buf[tmp_size] && (*tmp >= ' ' && *tmp <= 'z')) { + tmp = brc_getrecord(tmp, tmp_name, &tmp_num, tmp_list); + if(strncmp(tmp_name, currboard, BRC_STRLEN)) + ptr = brc_putrecord(ptr, tmp_name, tmp_num, tmp_list); + } + brc_size = (int)(ptr - brc_buf); + + if((fd = open(dirfile, O_WRONLY | O_CREAT, 0644)) != -1) { + ftruncate(fd, 0); + write(fd, brc_buf, brc_size); + close(fd); + } + brc_changed = 0; + } +} + +static void read_brc_buf() { + char dirfile[STRLEN]; + int fd; + + if(brc_buf[0] == '\0') { + setuserfile(dirfile, fn_boardrc); + if((fd = open(dirfile, O_RDONLY)) != -1) { + brc_size = read(fd, brc_buf, sizeof(brc_buf)); + close(fd); + } else { + brc_size = 0; + } + } +} + +extern int currbid; +extern unsigned int currbrdattr; +extern boardheader_t *bcache; + +int brc_initial(char *boardname) { + char *ptr; + if(strcmp(currboard, boardname) == 0) { + return brc_num; + } + brc_update(); + strcpy(currboard, boardname); + currbid = getbnum(currboard); + currbrdattr = bcache[currbid - 1].brdattr; + read_brc_buf(); + + ptr = brc_buf; + while(ptr < &brc_buf[brc_size] && (*ptr >= ' ' && *ptr <= 'z')) { + ptr = brc_getrecord(ptr, brc_name, &brc_num, brc_list); + if (strncmp(brc_name, currboard, BRC_STRLEN) == 0) + return brc_num; + } + strncpy(brc_name, boardname, BRC_STRLEN); + brc_num = brc_list[0] = 1; + return 0; +} + +void brc_addlist(char *fname) { + int ftime, n, i; + + if(!cuser.userlevel) + return; + + ftime = atoi(&fname[2]); + if(ftime <= brc_expire_time + /* || fname[0] != 'M' || fname[1] != '.' */ ) { + return; + } + if(brc_num <= 0) { + brc_list[brc_num++] = ftime; + brc_changed = 1; + return; + } + if((brc_num == 1) && (ftime < brc_list[0])) + return; + for(n = 0; n < brc_num; n++) { + if(ftime == brc_list[n]) { + return; + } else if(ftime > brc_list[n]) { + if(brc_num < BRC_MAXNUM) + brc_num++; + for(i = brc_num - 1; --i >= n; brc_list[i + 1] = brc_list[i]); + brc_list[n] = ftime; + brc_changed = 1; + return; + } + } + if(brc_num < BRC_MAXNUM) { + brc_list[brc_num++] = ftime; + brc_changed = 1; + } +} + +static int brc_unread_time(time_t ftime, int bnum, int *blist) { + int n; + + if(ftime <= brc_expire_time ) + return 0; + + if(brc_num <= 0) + return 1; + for(n = 0; n < bnum; n++) { + if(ftime > blist[n]) + return 1; + else if(ftime == blist[n]) + return 0; + } + return 0; +} + +int brc_unread(char *fname, int bnum, int *blist) { + int ftime, n; + + ftime = atoi(&fname[2]); + + if(ftime <= brc_expire_time ) + return 0; + + if(brc_num <= 0) + return 1; + for(n = 0; n < bnum; n++) { + if(ftime > blist[n]) + return 1; + else if(ftime == blist[n]) + return 0; + } + return 0; +} + +#define BRD_UNREAD 1 +#define BRD_FAV 2 +#define BRD_ZAP 4 +#define BRD_TAG 8 + +typedef struct { + int bid, *total; + time_t *lastposttime; + boardheader_t *bh; + unsigned int myattr; +} boardstat_t; + +extern time_t login_start_time; +extern int numboards; +static int *zapbuf=NULL,*favbuf; +static boardstat_t *nbrd; + +#define STR_BBSRC ".bbsrc" +#define STR_FAV ".fav" + +void init_brdbuf() { + register int n, size; + char fname[60]; + + /* MAXBOARDS ==> �ܦh�ݱo�� 4 �ӷs�O */ + n = numboards + 4; + size = n * sizeof(int); + zapbuf = (int *) malloc(size); + favbuf = (int *) malloc(size); + + memset(favbuf,0,size); + + while(n) + zapbuf[--n] = login_start_time; + setuserfile(fname, STR_BBSRC); + if((n = open(fname, O_RDONLY, 0600)) != -1) { + read(n, zapbuf, size); + close(n); + } + setuserfile(fname, STR_FAV); + if((n = open(fname, O_RDONLY, 0600)) != -1) { + read(n, favbuf, size); + close(n); + } + + if(!nbrd) + nbrd = (boardstat_t *)malloc(MAX_BOARD * sizeof(boardstat_t)); + brc_expire_time = login_start_time - 365 * 86400; +} + +void save_brdbuf() { + int fd, size; + char fname[60]; + + if(!zapbuf) return; + setuserfile(fname, STR_BBSRC); + if((fd = open(fname, O_WRONLY | O_CREAT, 0600)) != -1) { + size = numboards * sizeof(int); + write(fd, zapbuf, size); + close(fd); + } + setuserfile(fname, STR_FAV); + if((fd = open(fname, O_WRONLY | O_CREAT, 0600)) != -1) { + size = numboards * sizeof(int); + write(fd, favbuf, size); + close(fd); + } +} + +extern char *fn_visable; + +int Ben_Perm(boardheader_t *bptr) { + register int level,brdattr; + register char *ptr; + + level = bptr->level; + brdattr = bptr->brdattr; + + if(HAS_PERM(PERM_SYSOP)) + return 1; + + ptr = bptr->BM; + if(is_BM(ptr)) + return 1; + + /* ���K�ݪO�G�ֹﭺ�u�O�D���n�ͦW�� */ + + if(brdattr & BRD_HIDE) { /* ���� */ + if( hbflcheck((int)(bptr-bcache) + 1, currutmp->uid) ){ + if(brdattr & BRD_POSTMASK) + return 0; + else + return 2; + } else + return 1; + } + /* ����\Ū�v�� */ + if(level && !(brdattr & BRD_POSTMASK) && !HAS_PERM(level)) + return 0; + + return 1; +} + +extern char currauthor[]; +extern int b_lines; +extern char currowner[]; + +static int have_author(char* brdname) { + char dirname[100]; + + sprintf(dirname, "���b�j�M�@��[33m%s[m �ݪO:[1;33m%s[0m.....", + currauthor,brdname); + move(b_lines, 0); + clrtoeol(); + outs(dirname); + refresh(); + + setbdir(dirname, brdname); + str_lower(currowner, currauthor); + + return search_rec(dirname, cmpfowner); +} + +static int check_newpost(boardstat_t *ptr) { /* Ptt �� */ + int tbrc_list[BRC_MAXNUM], tbrc_num; + char bname[BRC_STRLEN]; + char *po; + time_t ftime; + + ptr->myattr &= ~BRD_UNREAD; + if(ptr->bh->brdattr & BRD_GROUPBOARD) + return 0; + + if(*(ptr->total) == 0) + setbtotal(ptr->bid); + if(*(ptr->total) == 0) return 0; + ftime = *(ptr->lastposttime); + read_brc_buf(); + po = brc_buf; + while(po < &brc_buf[brc_size] && (*po >= ' ' && *po <= 'z')) { + po = brc_getrecord(po, bname, &tbrc_num, tbrc_list); + if(strncmp(bname, ptr->bh->brdname, BRC_STRLEN) == 0) { + if(brc_unread_time(ftime,tbrc_num,tbrc_list)) { + ptr->myattr |= BRD_UNREAD; + } + return 1; + } + } + + ptr->myattr |= BRD_UNREAD; + return 1; +} + +extern int currmode; +extern struct bcache_t *brdshm; +static int brdnum; +int class_bid = 0; +static int yank_flag = 1; +static void load_uidofgid(const int gid, const int type){ + boardheader_t *bptr,*currbptr; + int n; + currbptr = &bcache[gid-1]; + for(n=0;n<numboards;n++) + { + bptr = brdshm->sorted[type][n]; + if(bptr->brdname[0]=='\0') continue; + if(bptr->gid == gid) + { + if(currbptr == &bcache[gid-1]) + currbptr->firstchild[type]=bptr; + else + { + currbptr->next[type]=bptr; + currbptr->parent=&bcache[gid-1]; + } + currbptr=bptr; + } + } + if(currbptr == &bcache[gid-1]) + currbptr->firstchild[type]=(boardheader_t *) ~0; + else + currbptr->next[type]=(boardheader_t *) ~0; +} +static boardstat_t * addnewbrdstat(int n, int state) +{ + boardstat_t *ptr=&nbrd[brdnum++]; + boardheader_t *bptr = &bcache[n]; + ptr->total = &(brdshm->total[n]); + ptr->lastposttime = &(brdshm->lastposttime[n]); + ptr->bid = n+1; + ptr->myattr=0; + ptr->myattr=(favbuf[n]&~BRD_ZAP); + if(zapbuf[n] == 0) + ptr->myattr|=BRD_ZAP; + ptr->bh = bptr; + if((bptr->brdattr & BRD_HIDE) && state == 1) + bptr->brdattr |= BRD_POSTMASK; + check_newpost(ptr); + return ptr; +} + +static void load_boards(char *key) { + boardheader_t *bptr = NULL; + int type=cuser.uflag & BRDSORT_FLAG?1:0; + register int i,n; + register int state ; + + if(class_bid>0) + { + bptr = &bcache[class_bid-1]; + if(bptr->firstchild[type]==NULL) + load_uidofgid(class_bid,type); + } + brdnum = 0; + if(class_bid==0) + for(i=0 ; i < numboards; i++) + { + + if( (bptr = brdshm->sorted[type][i]) == NULL ) + continue; + n = (int)( bptr - bcache); + if(!bptr->brdname[0] || bptr->brdattr & BRD_GROUPBOARD || + !((state = Ben_Perm(bptr)) || (currmode & MODE_MENU)) || + (yank_flag == 0 && !(favbuf[n]&BRD_FAV)) || + (yank_flag == 1 && !zapbuf[n]) || + (key[0] && !strcasestr(bptr->title, key)) + ) continue; + addnewbrdstat(n, state); + } + else + for(bptr=bptr->firstchild[type]; bptr!=(boardheader_t *)~0; + bptr=bptr->next[type]) + { + n = (int)( bptr - bcache); + if(!((state = Ben_Perm(bptr)) || (currmode & MODE_MENU)) + ||(yank_flag == 0 && !(favbuf[n]&BRD_FAV)) + ||(yank_flag == 1 && !zapbuf[n]) || + (key[0] && !strcasestr(bptr->title, key))) continue; + addnewbrdstat(n, state); + } +} + +static int search_board() { + int num; + char genbuf[IDLEN + 2]; + move(0, 0); + clrtoeol(); + CreateNameList(); + for(num = 0; num < brdnum; num++) + AddNameList(nbrd[num].bh->brdname); + namecomplete(MSG_SELECT_BOARD, genbuf); + + for (num = 0; num < brdnum; num++) + if (!strcasecmp(nbrd[num].bh->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 = *(ptr->total); + num = total + 1; + if((ptr->myattr&BRD_UNREAD) &&(fd = open(dirfile, O_RDWR)) > 0) { + if(!brc_initial(ptr->bh->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(fname,brc_num,brc_list)) + 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(fname,brc_num,brc_list)) + break; + num++; + } + } + close(fd); + } + if(num < 0) + num = 0; + return num; +} + +static void brdlist_foot() { + prints("\033[34;46m ��ܬݪO \033[31;47m (c)\033[30m�s�峹�Ҧ� " + "\033[31m(v/V)\033[30m�аO�wŪ/��Ū \033[31m(y)\033[30m�z��%s" + " \033[31m(z)\033[30m������� \033[m", + yank_flag==0 ? "�̷R" : yank_flag==1 ? "����" : "����"); +} + +extern unsigned int currstat; +extern char *BBSName; + +static void show_brdlist(int head, int clsflag, int newflag) { + int myrow = 2; + if(class_bid == 1) { + currstat = CLASS; + myrow = 6; + showtitle("�����ݪO", BBSName); + movie(0); + move(1, 0); + prints( + " " + "�� �~�X\033[33m��\n" + " ��X \033[m " + "���i\033[47m��\033[40m�i�i����\n"); + prints( + " \033[44m �s�s�s�s�s�s�s�s " + "\033[33m��\033[m\033[44m �����i�i�i�������� \033[m\n" + " \033[44m " + "\033[33m \033[m\033[44m �����i�i�i������ ��\033[m\n" + " �s�s�s�s�s�s�s�s \033[33m" + "�x\033[m ���i�i�i�i�� ��\n" + " \033[33m��" + "�X�X\033[m �� �X��\033[m"); + } else if (clsflag) { + showtitle("�ݪO�C��", BBSName); + prints("[��]�D��� [��]�\\Ū [����]��� [y]���J [S]�Ƨ� [/]�j�M " + "[TAB]��K�E�ݪO [h]�D�U\n" + "\033[7m%-20s ���O ��H%-31s�벼 �O �D \033[m", + newflag ? "�`�� ��Ū �� �O" : " �s�� �� �O", + " �� �� �� �z"); + move(b_lines, 0); + brdlist_foot(); + } + + if(brdnum > 0) { + boardstat_t *ptr; + static char *color[8]={"","\033[32m", + "\033[33m","\033[36m","\033[34m","\033[1m", + "\033[1;32m","\033[1;33m"}; + static char *unread[2]={"\33[37m \033[m","\033[1;31m��\033[m"}; + + while(++myrow < b_lines) { + move(myrow, 0); + clrtoeol(); + if(head < brdnum) { + ptr = &nbrd[head++]; + if(class_bid == 1) + prints(" "); + if(!newflag) { + prints("%5d%c%s", head, + !(ptr->bh->brdattr & BRD_HIDE) ? ' ': + (ptr->bh->brdattr & BRD_POSTMASK) ? ')' : '-', + (ptr->myattr & BRD_TAG) ? "D " : + (ptr->myattr & BRD_ZAP) ? "- " : + (ptr->bh->brdattr & BRD_GROUPBOARD) ? " " : + unread[ptr->myattr&BRD_UNREAD]); + } else if(ptr->myattr&BRD_ZAP) { + ptr->myattr &= ~BRD_UNREAD; + prints(" �� ��"); + } else { + if(newflag) { + if((ptr->bh->brdattr & BRD_GROUPBOARD)) + prints(" "); + else + prints("%6d%s", (int)(*(ptr->total)), + unread[ptr->myattr&BRD_UNREAD]); + } + } + if(class_bid != 1) { + prints("%s%-13s\033[m%s%5.5s\033[0;37m%2.2s\033[m" + "%-35.35s%c %.13s", + (ptr->myattr & BRD_FAV)?"\033[1;36m":"", + ptr->bh->brdname, + color[(unsigned int) + (ptr->bh->title[1] + ptr->bh->title[2] + + ptr->bh->title[3] + ptr->bh->title[0]) & 07], + ptr->bh->title, ptr->bh->title+5, ptr->bh->title+7, + (ptr->bh->brdattr & BRD_BAD) ? 'X' : + " ARBCDEFGHI"[ptr->bh->bvote], + ptr->bh->BM); + refresh(); + } else { + prints("%-40.40s %.13s", ptr->bh->title + 7, ptr->bh->BM); + } + } + clrtoeol(); + } + } +} + +static char *choosebrdhelp[] = { + "\0�ݪO��滲�U����", + "\01���O", + "(p)(��)/(n)(��)�W�@�ӬݪO / �U�@�ӬݪO", + "(P)(^B)(PgUp) �W�@���ݪO", + "(N)(^F)(PgDn) �U�@���ݪO", + "($)/(s)/(/) �̫�@�ӬݪO / �j�M�ݪO / �H����j�M�ݪO����r", + "(�Ʀr) ���ܸӶ���", + "\01�i�����O", + "(^W) �g���F �ڦb����", + "(r)(��)(Rtn) �i�J�h�\\��\\Ū���", + "(q)(��) �^��D���", + "(z)(Z) �q�\\/�ϭq�\\�ݪO �q�\\/�ϭq�\\�Ҧ��ݪO", + "(y) �ڪ��̷R/�q�\\�ݪO/�X�Ҧ��ݪO", + "(v/V) �q�q�ݧ�/������Ū", + "(S) ���Ӧr��/�����Ƨ�", + "(t/^T/^A/^D) �аO�ݪO/�����Ҧ��аO/�w�аO���[�J�ڪ��̷R/�����ڪ��̷R", + "(m) ��ݪO�[�J�ڪ��̷R", + "\01�p�ժ����O", + "(E/W/B) �]�w�ݪO/�]�w�p�ճƧ�/�}�s�ݪO", + "(^P) ���ʤw�аO�ݪO�즹����", + NULL +}; + + +static void set_menu_BM(char *BM) { + if(HAS_PERM(PERM_ALLBOARD) || is_BM(BM)) { + currmode |= MODE_MENU; + cuser.userlevel |= PERM_SYSSUBOP; + } +} + +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern int t_lines; +extern char *fn_notes; +static char *privateboard = +"\n\n\n\n �藍�_ ���O�ثe�u��ݪO�n�Ͷi�J �Х��V�O�D�ӽФJ�ҳ\\�i"; +static void dozap(int num){ + boardstat_t *ptr; + ptr = &nbrd[num]; + ptr->myattr ^= BRD_ZAP; + if(ptr->bh->brdattr & BRD_NOZAP) ptr->myattr &= ~BRD_ZAP; + if(!(ptr->myattr & BRD_ZAP) ) check_newpost(ptr); + zapbuf[ptr->bid-1] = (ptr->myattr&BRD_ZAP?0:login_start_time); +} +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]=""; +#if HAVE_SEARCH_ALL + char genbuf[200]; +#endif + extern time_t board_visit_time; + + setutmpmode(newflag ? READNEW : READBRD); + brdnum = 0; + if(!cuser.userlevel) /* guest yank all boards */ + yank_flag = 2; + + do { + if(brdnum <= 0) { + load_boards(keyword); + if(brdnum <= 0) { + if(keyword[0]!=0) + { + mprints(b_lines-1,0,"�S������ݪO���D��������r " + "(���D���`�N�ݪO���D�R�W)"); + pressanykey(); + keyword[0]=0; + brdnum = -1; + continue; + } + if(yank_flag<2) + { + brdnum = -1; + yank_flag++; + continue; + } + if(HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU)) { + if(m_newbrd(0) == -1) + break; + brdnum = -1; + continue; + } else + break; + } + head = -1; + } + + if(num < 0) + num = 0; + else if(num >= brdnum) + num = brdnum - 1; + + if(head < 0) { + if(newflag) { + tmp = num; + while(num < brdnum) { + ptr = &nbrd[num]; + if(ptr->myattr&BRD_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(class_bid == 1) + ch = cursor_key(7 + num - head, 10); + else + ch = cursor_key(3 + num - head, 0); + + switch(ch) { + case Ctrl('W'): + whereami(0,NULL,NULL); + head=-1; + break; + case 'e': + case KEY_LEFT: + case EOF: + ch = 'q'; + case 'q': + if(keyword[0]) + { + keyword[0]=0; + brdnum=-1; + ch=' '; + } + break; + case 'c': + show_brdlist(head, 1, newflag ^= 1); + 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 Ctrl('C'): + cal(); + show_brdlist(head, 1, newflag); + break; + case Ctrl('I'): + t_idle(); + show_brdlist(head, 1, newflag); + break; + case KEY_UP: + case 'p': + case 'k': + if (num-- <= 0) + num = brdnum - 1; + break; + case 't': + ptr = &nbrd[num]; + ptr->myattr ^= BRD_TAG; + favbuf[ptr->bid-1]=ptr->myattr; + 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 'F': + case 'f': + if(class_bid && HAS_PERM(PERM_SYSOP)) + { + bcache[class_bid-1].firstchild[cuser.uflag&BRDSORT_FLAG?1:0] + =NULL; + brdnum = -1; + } + break; + case 'h': + show_help(choosebrdhelp); + show_brdlist(head, 1, newflag); + break; + case '/': + getdata_buf(b_lines-1,0,"�п�J�ݪO��������r:",keyword, 12, DOECHO); + brdnum=-1; + break; + case 'S': + cuser.uflag ^= BRDSORT_FLAG; + brdnum = -1; + break; + case 'y': + if(class_bid==0) + yank_flag = (yank_flag+1)%3; + else + yank_flag = yank_flag%2+1; + brdnum = -1; + break; + case Ctrl('D'): + for(tmp = 0; tmp < numboards; tmp++) + { + if(favbuf[tmp] & BRD_TAG) + { + favbuf[tmp] &= ~BRD_FAV; + favbuf[tmp] &= ~BRD_TAG; + } + } + brdnum = -1; + break; + case Ctrl('A'): + for(tmp = 0; tmp < numboards; tmp++) + { + if(favbuf[tmp] & BRD_TAG) + { + favbuf[tmp] |= BRD_FAV; + favbuf[tmp] &= ~BRD_TAG; + } + } + brdnum = -1; + break; + case Ctrl('T'): + for(tmp = 0; tmp < numboards; tmp++) + favbuf[tmp] &= ~BRD_TAG; + brdnum = -1; + break; + case Ctrl('P'): + if(class_bid!=0 && + (HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU))) { + for(tmp = 0; tmp < numboards; tmp++) { + boardheader_t *bh=&bcache[tmp]; + if(!(favbuf[tmp]&BRD_TAG) || bh->gid==class_bid) + continue; + favbuf[tmp] &= ~BRD_TAG; + if(bh->gid != class_bid) + { + bh->gid = class_bid; + substitute_record(FN_BOARD, bh, + sizeof(boardheader_t), tmp+1); + reset_board(tmp+1); + log_usies("SetBoardGID", bh->brdname); + } + } + brdnum = -1; + } + break; + case 'm': + if(HAS_PERM(PERM_BASIC)) { + ptr = &nbrd[num]; + ptr->myattr ^= BRD_FAV; + favbuf[ptr->bid-1]=ptr->myattr; + head = 9999; + } + break; + case 'z': + if(HAS_PERM(PERM_BASIC)) { + dozap(num); + head = 9999; + } + break; + case 'Z': /* Ptt */ + if(HAS_PERM(PERM_BASIC)) { + for(tmp = 0; tmp < brdnum; tmp++) { + dozap(tmp); + } + head = 9999; + } + break; + case 'v': + case 'V': + ptr = &nbrd[num]; + brc_initial(ptr->bh->brdname); + if(ch == 'v') { + ptr->myattr &= ~BRD_UNREAD; + zapbuf[ptr->bid-1] = time((time_t *) &brc_list[0]); + } else + { + zapbuf[ptr->bid-1] = brc_list[0] = 1; + ptr->myattr |= BRD_UNREAD; + } + brc_num = brc_changed = 1; + brc_update(); + show_brdlist(head, 0, newflag); + break; + case 's': + if((tmp = search_board()) == -1) { + show_brdlist(head, 1, newflag); + break; + } + num = tmp; + case 'E': + if(HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU)) { + ptr = &nbrd[num]; + move(1,1); + clrtobot(); + m_mod_board(ptr->bh->brdname); + brdnum = -1; + } + break; + case 'R': + if(HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU)) { + m_newbrd(1); + brdnum = -1; + } + break; + case 'B': + if(HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU)) { + m_newbrd(0); + brdnum = -1; + } + break; + case 'W': + if(class_bid > 0 && + (HAS_PERM(PERM_SYSOP) || (currmode & MODE_MENU))) { + b_note_edit_bname(class_bid); + brdnum = -1; + } + break; + case KEY_RIGHT: + case '\n': + case '\r': + case 'r': + { + char buf[STRLEN]; + + ptr = &nbrd[num]; + + if(!(ptr->bh->brdattr & BRD_GROUPBOARD)) { /* �Dsub class */ + if(!(ptr->bh->brdattr & BRD_HIDE) || + (ptr->bh->brdattr & BRD_POSTMASK)) { + brc_initial(ptr->bh->brdname); + + if(newflag) { + setbdir(buf, currboard); + tmp = unread_position(buf, ptr); + head = tmp - t_lines / 2; + getkeep(buf, head > 1 ? head : 1, tmp + 1); + } + board_visit_time = zapbuf[ptr->bid-1]; + if(!(ptr->myattr&BRD_ZAP)) + time((time_t *) &zapbuf[ptr->bid-1]); + Read(); + check_newpost(ptr); + head = -1; + setutmpmode(newflag ? READNEW : READBRD); + } else { + setbfile(buf, ptr->bh->brdname, FN_APPLICATION); + if(more(buf,YEA)==-1) { + move(1,0); + clrtobot(); + outs(privateboard); + pressanykey(); + } + head = -1; + } + } else { /* sub class */ + move(12,1); + bidtmp = class_bid; + currmodetmp =currmode; + tmp1=num; + num=0; + class_bid = ptr->bid; + if (!(currmode & MODE_MENU))/*�p�G�٨S���p�ժ��v�� */ + set_menu_BM(ptr->bh->BM); + + if(time(NULL) < ptr->bh->bupdate) { + setbfile(buf, ptr->bh->brdname, fn_notes); + if(more(buf, NA) != -1) + pressanykey(); + } + tmp=currutmp->brc_id; + currutmp->brc_id=ptr->bid; + choose_board(0); + currmode = currmodetmp; /* ���}������N���v�������� */ + num=tmp1; + class_bid = bidtmp; + currutmp->brc_id=tmp; + brdnum = -1; + } + } + } + } while(ch != 'q'); + save_brdbuf(); +} + +int root_board() { + class_bid = 1; + yank_flag = 1; + choose_board(0); + return 0; +} + +int Boards() { + class_bid = 0; + yank_flag = 0; + choose_board(0); + return 0; +} + + +int New() { + int mode0 = currutmp->mode; + int stat0 = currstat; + + class_bid = 0; + choose_board(1); + currutmp->mode = mode0; + currstat = stat0; + return 0; +} + +/* +int v_favorite(){ + char fname[256]; + char inbuf[2048]; + FILE* fp; + int nGroup; + char* strtmp; + + setuserfile(fname,str_favorite); + + if (!(fp=fopen(fname,"r"))) + return -1; + move(0,0); + clrtobot(); + fgets(inbuf,sizeof(inbuf),fp); + nGroup=atoi(inbuf); + + currutmp->nGroup=0; + currutmp->ninRoot=0; + + while(nGroup!=currutmp->nGroup+1){ + fgets(inbuf,sizeof(inbuf),fp); + prints("%s\n",strtmp=strtok(inbuf," \n")); + strcpy(currutmp->gfavorite[currutmp->nGroup++],strtmp); + while((strtmp=strtok(NULL, " \n"))){ + prints(" %s %d\n",strtmp,getbnum(strtmp)); + } + currutmp->nGroup++; + } + prints("+++%d+++\n",currutmp->nGroup); + + fgets(inbuf,sizeof(inbuf),fp); + + for(strtmp=strtok(inbuf, " \n");strtmp;strtmp=strtok(NULL, " \n")){ + if (strtmp[0]!='#') + prints("*** %s %d\n",strtmp, getbnum(strtmp)); + else + prints("*** %s %d\n",strtmp+1, -1); + currutmp->ninRoot++; + } + + fclose(fp); + pressanykey(); + return 0; +} +*/ diff --git a/mbbsd/cache.c b/mbbsd/cache.c new file mode 100644 index 00000000..73f8ac5b --- /dev/null +++ b/mbbsd/cache.c @@ -0,0 +1,1053 @@ +/* $Id: cache.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <errno.h> +#include <time.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/sem.h> + +#ifdef __FreeBSD__ +#include <machine/param.h> +#endif + +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +#ifndef __FreeBSD__ +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 + +int fcache_semid; + +/* 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 long retv; +#if !defined(_BBS_UTIL_C_) + log_usies("SAFE_SLEEP ", "avoid hang"); +#endif + sigemptyset(&set); + sigaddset(&set,SIGALRM); + sigprocmask(SIG_UNBLOCK,&set,NULL); + retv=sleep(seconds); + sigprocmask(SIG_BLOCK,&set,NULL); + return retv; + } + return sleep(seconds); +} + +#if defined(_BBS_UTIL_C_) +static void setapath(char *buf, char *boardname) { + sprintf(buf, "man/boards/%s", boardname); +} + +static char *str_dotdir = ".DIR"; + +static void setadir(char *buf, char *path) { + sprintf(buf, "%s/%s", path, str_dotdir); +} +#endif + +static void attach_err(int shmkey, char *name) { + fprintf(stderr, "[%s error] key = %x\n", name, shmkey); + fprintf(stderr, "errno = %d: %s\n", errno, strerror(errno)); + exit(1); +} + +static void *attach_shm(int shmkey, int shmsize) { + void *shmptr; + int shmid; + + char *empty_addr; + /* set up one page in-accessible -- jochang */ + { + int fd = open("/dev/zero",O_RDONLY); + int size = ((shmsize + 4095) / 4096) * 4096; + + munmap( + (empty_addr=mmap(0,4096+size,PROT_NONE,MAP_PRIVATE,fd,0))+4096 + ,size); + + close(fd); + } + + shmid = shmget(shmkey, shmsize, 0); + if(shmid < 0) { + shmid = shmget(shmkey, shmsize, IPC_CREAT | 0600); + if(shmid < 0) + attach_err(shmkey, "shmget"); + shmptr = (void *)shmat(shmid, NULL, 0); + if(shmptr == (void *)-1) + attach_err(shmkey, "shmat"); + } else { + shmptr = (void *)shmat(shmid, NULL, 0); + if(shmptr == (void *)-1) + attach_err(shmkey, "shmat"); + } + + /* unmap the page -- jochang */ + { + munmap(empty_addr,4096); + } + return shmptr; +} + + +#define SEM_FLG 0600 /* semaphore mode */ + +/* ----------------------------------------------------- */ +/* semaphore : for critical section */ +/* ----------------------------------------------------- */ +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; + semop(semid, &sops, 1); +} + +/* 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. +*/ +uhash_t *uhash; + +/* attach_uhash should be called before using uhash */ +void attach_uhash() { + uhash = attach_shm(UHASH_KEY, sizeof(*uhash)); + if(!uhash->loaded) /* assume fresh shared memory is zeroed */ + exit(1); +} + +void add_to_uhash(int n, char *id) { + int *p, h = StringHash(id); + strcpy(uhash->userid[n], id); + + p = &(uhash->hash_head[h]); + + while(*p != -1) + p = &(uhash->next_in_hash[*p]); + + uhash->next_in_hash[*p = n] = -1; +} + +/* note: after remove_from_uhash(), you should add_to_uhash() + (likely with a different name) */ +void remove_from_uhash(int n) { + int h = StringHash(uhash->userid[n]); + int *p = &(uhash->hash_head[h]); + + while(*p != -1 && *p != n) + p = &(uhash->next_in_hash[*p]); + if(*p == n) + *p = uhash->next_in_hash[n]; +} + +int setumoney(int uid, int money) { + uhash->money[uid-1]=money; + passwd_update_money(uid); + return uhash->money[uid-1]; +} + +int deumoney(int uid, int money) { + if(money<0 && uhash->money[uid-1]<-money) + return setumoney(uid,0); + else + return setumoney(uid,uhash->money[uid-1]+money); +} +int demoney(int money) { + extern int usernum; + return deumoney(usernum,money); +} +int moneyof(int uid){ /* ptt ��i�����B�z�IJv */ + return uhash->money[uid-1]; +} +int searchuser(char *userid) { + int h,p; + + h = StringHash(userid); + p = uhash->hash_head[h]; + + while(p != -1) { + if(strcasecmp(uhash->userid[p],userid) == 0) { + strcpy(userid,uhash->userid[p]); + return p + 1; + } + p = uhash->next_in_hash[p]; + } + return 0; +} + +#if !defined(_BBS_UTIL_C_) +extern userec_t xuser; + +int getuser(char *userid) { + int uid; + + if((uid = searchuser(userid))) + passwd_query(uid, &xuser); + return uid; +} + +char *getuserid(int num) { + if(--num >= 0 && num < MAX_USERS) + return ((char *) uhash->userid[num]); + return NULL; +} + +void setuserid(int num, char *userid) { + if(num > 0 && num <= MAX_USERS) { + if(num > uhash->number) + uhash->number = num; + else + remove_from_uhash(num-1); + add_to_uhash(num-1,userid); + } +} + +/* 0 ==> ��L���b�� */ +/* 1 ==> �إ߷s�b�� */ +/* should do it by searching "" in the hash */ +int searchnewuser(int mode) { + register int i, num; + + num = uhash->number; + i = 0; + + /* ������o�䤣�� hash table �h��ӭn�� linear search? */ + while(i < num) { + if(!uhash->userid[i++][0]) + return i; + } + if(mode && (num < MAX_USERS)) + return num + 1; + return 0; +} + +char *u_namearray(char buf[][IDLEN + 1], int *pnum, char *tag) { + register struct uhash_t *reg_ushm = uhash; + register char *ptr, tmp; + register int n, total; + char tagbuf[STRLEN]; + int ch, ch2, num; + + if(*tag == '\0') { + *pnum = reg_ushm->number; + return reg_ushm->userid[0]; + } + for(n = 0; tag[n]; n++) + tagbuf[n] = chartoupper(tag[n]); + tagbuf[n] = '\0'; + ch = tagbuf[0]; + ch2 = ch - 'A' + 'a'; + total = reg_ushm->number; + for(n = num = 0; n < total; n++) { + ptr = reg_ushm->userid[n]; + tmp = *ptr; + if(tmp == ch || tmp == ch2) { + if(chkstr(tag, tagbuf, ptr)) + strcpy(buf[num++], ptr); + } + } + *pnum = num; + return buf[0]; +} +#endif + +/*-------------------------------------------------------*/ +/* .UTMP cache */ +/*-------------------------------------------------------*/ +struct utmpfile_t *utmpshm=NULL; + +void resolve_utmp() { + if(utmpshm == NULL) { + utmpshm = attach_shm(UTMPSHM_KEY, sizeof(*utmpshm)); + } +} + +userinfo_t *currutmp = NULL; + +#if !defined(_BBS_UTIL_C_) +extern unsigned int currstat; +extern userec_t cuser; + +void setutmpmode(int mode) { + if(currstat != mode) + currutmp->mode = currstat = mode; + + /* �l�ܨϥΪ� */ + if(HAS_PERM(PERM_LOGUSER)) { + time_t now = time(NULL); + char msg[200]; + sprintf(msg, "%s setutmpmode to %s(%d) at %s", + cuser.userid, modestring(currutmp, 0), mode, Cdate(&now)); + log_user(msg); + } +} +#endif +/* +static int cmputmpuserid(userinfo_t ** i, userinfo_t ** j) { + return strcasecmp((*i)->userid, (*j)->userid); +} + +static int cmputmpmode(userinfo_t ** i, userinfo_t ** j) { + return (*i)->mode-(*j)->mode; +} + +static int cmputmpidle(userinfo_t ** i, userinfo_t ** j) { + return (*i)->lastact-(*j)->lastact; +} + +static int cmputmpfrom(userinfo_t ** i, userinfo_t ** j) { + return strcasecmp((*i)->from, (*j)->from); +} + +static int cmputmpfive(userinfo_t ** i, userinfo_t ** j) { + int type; + if((type=(*j)->five_win - (*i)->five_win)) + return type; + if((type=(*i)->five_lose - (*j)->five_lose)) + return type; + return (*i)->five_tie-(*j)->five_tie; +} +static int cmputmpsex(userinfo_t ** i, userinfo_t ** j) { + static int ladyfirst[]={1,0,1,0,1,0,3,3}; + return ladyfirst[(*i)->sex]-ladyfirst[(*j)->sex]; +} +static int cmputmppid(userinfo_t ** i, userinfo_t ** j) { + return (*i)->pid-(*j)->pid; +} +static int cmputmpuid(userinfo_t ** i, userinfo_t ** j) { + return (*i)->uid-(*j)->uid; +} +*/ +static int cmputmpuserid(const void *i, const void *j){ + return strcasecmp((*((userinfo_t**)i))->userid, (*((userinfo_t**)j))->userid); +} + +static int cmputmpmode(const void *i, const void *j){ + return (*((userinfo_t**)i))->mode-(*((userinfo_t**)j))->mode; +} + +static int cmputmpidle(const void *i, const void *j){ + return (*((userinfo_t**)i))->lastact-(*((userinfo_t**)j))->lastact; +} + +static int cmputmpfrom(const void *i, const void *j){ + return strcasecmp((*((userinfo_t**)i))->from, (*((userinfo_t**)j))->from); +} + +static int cmputmpfive(const void *i, const void *j){ + int type; + if((type=(*((userinfo_t**)j))->five_win - (*((userinfo_t**)i))->five_win)) + return type; + if((type=(*((userinfo_t**)i))->five_lose - (*((userinfo_t**)j))->five_lose)) + return type; + return (*((userinfo_t**)i))->five_tie-(*((userinfo_t**)j))->five_tie; +} + +static int cmputmpsex(const void *i, const void *j){ + static int ladyfirst[]={1,0,1,0,1,0,3,3}; + return ladyfirst[(*((userinfo_t**)i))->sex]-ladyfirst[(*((userinfo_t**)j))->sex]; +} +static int cmputmppid(const void *i, const void *j){ + return (*((userinfo_t**)i))->pid-(*((userinfo_t**)j))->pid; +} +static int cmputmpuid(const void *i, const void *j){ + return (*((userinfo_t**)i))->uid-(*((userinfo_t**)j))->uid; +} +void sort_utmp() +{ + time_t now=time(NULL); + int count, i, ns; + userinfo_t *uentp; + + if(now-utmpshm->uptime<60 && (now==utmpshm->uptime || utmpshm->busystate)) + return; /* lazy sort */ + utmpshm->busystate=1; + utmpshm->uptime = now; + ns=(utmpshm->currsorted?0:1); + + for(uentp = &utmpshm->uinfo[0], count=0, i=0; + i< USHM_SIZE; i++,uentp = &utmpshm->uinfo[i]) + if(uentp->pid) + { + utmpshm->sorted[ns][0][count++]= uentp; + } + utmpshm->number = count; + qsort(utmpshm->sorted[ns][0],count,sizeof(userinfo_t*),cmputmpuserid); + memcpy(utmpshm->sorted[ns][1],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][2],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][3],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][4],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][5],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][6],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + memcpy(utmpshm->sorted[ns][7],utmpshm->sorted[ns][0], + sizeof(userinfo_t *)*count); + qsort(utmpshm->sorted[ns][1], count, sizeof(userinfo_t *), cmputmpmode ); + qsort(utmpshm->sorted[ns][2], count, sizeof(userinfo_t *), cmputmpidle ); + qsort(utmpshm->sorted[ns][3], count, sizeof(userinfo_t *), cmputmpfrom ); + qsort(utmpshm->sorted[ns][4], count, sizeof(userinfo_t *), cmputmpfive ); + qsort(utmpshm->sorted[ns][5], count, sizeof(userinfo_t *), cmputmpsex ); + qsort(utmpshm->sorted[ns][6], count, sizeof(userinfo_t *), cmputmpuid ); + qsort(utmpshm->sorted[ns][7], count, sizeof(userinfo_t *), cmputmppid ); + utmpshm->currsorted=ns; + utmpshm->busystate=0; +} +// Ptt:�o��[�Jhash�[�� ��Ū�utmp +void getnewutmpent(userinfo_t *up) { + extern int errno; + register int i, p ; + register userinfo_t *uentp; + for(i = 0, p=StringHash(up->userid)%USHM_SIZE; i < USHM_SIZE; i++, p++) { + if(p==USHM_SIZE) p=0; + uentp = &(utmpshm->uinfo[p]); + if(!(uentp->pid)) { + memcpy(uentp, up, sizeof(userinfo_t)); + currutmp = uentp; + sort_utmp(); + return; + } + } + exit(1); +} + +int apply_ulist(int (*fptr)(userinfo_t *)) { + register userinfo_t *uentp; + register int i, state; + + for(i = 0; i < USHM_SIZE; i++) { + uentp = &(utmpshm->uinfo[i]); + if(uentp->pid && (PERM_HIDE(currutmp) || !PERM_HIDE(uentp))) + if((state = (*fptr) (uentp))) + return state; + } + return 0; +} + +userinfo_t *search_ulist(int uid) { + return search_ulistn(uid,1); +} + +#if !defined(_BBS_UTIL_C_) +extern int usernum; + +userinfo_t *search_ulist_pid(int pid) { + register int i=0, j, start = 0, end = utmpshm->number - 1; + register userinfo_t **ulist; + ulist=utmpshm->sorted[utmpshm->currsorted][7]; + for(i=((start+end)/2); ;i=(start+end)/2) + { + j=pid-ulist[i]->pid; + if(!j) + { + return (userinfo_t *) (ulist[i]); + } + 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 = utmpshm->number - 1; + register userinfo_t **ulist; + ulist=utmpshm->sorted[utmpshm->currsorted][6]; + for(i=((start+end)/2); ;i=(start+end)/2) + { + j= uid - ulist[i]->uid; + if(!j) + { + for(;i>0 && uid==ulist[i-1]->uid;i--);/* ����Ĥ@�� */ + if(uid==ulist[i+unum-1]->uid) + return (userinfo_t *) (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; +} + +int count_logins(int uid, int show) { + register int i=0, j, start = 0, end = utmpshm->number - 1, count; + register userinfo_t **ulist; + ulist=utmpshm->sorted[utmpshm->currsorted][6]; + for(i=((start+end)/2); ;i=(start+end)/2) + { + j = uid-ulist[i]->uid; + if(!j) + { + for(;i>0 && uid==ulist[i-1]->uid;i--);/* ����Ĥ@�� */ + for(count=0;uid==ulist[i+count]->uid;count++) + { + if(show) + prints("(%d) �ثe���A��: %-17.16s(�Ӧ� %s)\n", + count+1, modestring(ulist[i+count], 0), + ulist[i+count]->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(); + memset(uentp, 0, sizeof(userinfo_t)); +} + +#endif + +/*-------------------------------------------------------*/ +/* .BOARDS cache */ +/*-------------------------------------------------------*/ +extern char *fn_board; +extern int currbid; +bcache_t *brdshm; +boardheader_t *bcache; + +void touchdircache(int bid) +{ + int *i= (int *)&brdshm->dircache[bid - 1][0].filename[0]; + *i=0; +} + +void load_fileheader_cache(int bid, char *direct) +{ + int num=getbtotal(bid); + int n = num-DIRCACHESIZE+1; + if (brdshm->busystate!=1) + { + brdshm->busystate = 1; + get_records(direct, brdshm->dircache[bid - 1] , + sizeof(fileheader_t),n<1?1:n, DIRCACHESIZE); + brdshm->cachetotal[bid-1]=num; // cachetotal���] �H��A�藍�Υ���load + brdshm->busystate = 0; + } + else + {safe_sleep(1);} +} + +int get_fileheader_cache(int bid, char *direct, fileheader_t *headers, + int recbase, int nlines) +{ + int ret, n,num; + + num=getbtotal(bid); + + ret = num-recbase+1, + n = (num - DIRCACHESIZE+1); + + + if(brdshm->dircache[bid - 1][0].filename[0]=='\0') + load_fileheader_cache(bid, direct); + if (n<1) + n=recbase-1; + else + n=recbase-n; + if(n<0) n=0; + if (ret>nlines) ret=nlines; + memcpy(headers, &(brdshm->dircache[bid - 1][n]),sizeof(fileheader_t)*ret); + return ret; +} +static int cmpboardname(boardheader_t **brd, boardheader_t **tmp) { + return strcasecmp((*brd)->brdname, (*tmp)->brdname); +} +static int cmpboardclass(boardheader_t **brd, boardheader_t **tmp) { + return (strncmp((*brd)->title, (*tmp)->title, 4)<<8)+ + strcasecmp((*brd)->brdname, (*tmp)->brdname); +} +static void sort_bcache(){ + int i;/*critical section �����W�I�s �I�sreload_bcache or reset_board */ + for(i=0;i<brdshm->number;i++) + { + brdshm->sorted[1][i]=brdshm->sorted[0][i]=&bcache[i]; + } + qsort(brdshm->sorted[0], brdshm->number, sizeof(boardheader_t *), + (QCAST)cmpboardname); + qsort(brdshm->sorted[1], brdshm->number, sizeof(boardheader_t *), + (QCAST)cmpboardclass); +} +static void reload_bcache() { + if(brdshm->busystate) { + safe_sleep(1); + } +#if !defined(_BBS_UTIL_C_) + else { + int fd,i; + + brdshm->busystate = 1; + if((fd = open(fn_board, O_RDONLY)) > 0) { + brdshm->number = + read(fd, bcache, MAX_BOARD * sizeof(boardheader_t)) / + sizeof(boardheader_t); + close(fd); + } + memset(brdshm->lastposttime, 0, MAX_BOARD * sizeof(time_t)); + /* ���Ҧ� boards ��Ƨ�s��A�]�w uptime */ + brdshm->uptime = brdshm->touchtime; + log_usies("CACHE", "reload bcache"); + sort_bcache(); + for(i=0;i<brdshm->number;i++) + { + bcache[i].firstchild[0]=NULL; + bcache[i].firstchild[1]=NULL; + } + brdshm->busystate = 0; + } +#endif +} + +int numboards = -1; + +void resolve_boards() { + if(brdshm == NULL) { + brdshm = attach_shm(BRDSHM_KEY, sizeof(*brdshm)); + if(brdshm->touchtime == 0) + brdshm->touchtime = 1; + bcache = brdshm->bcache; + } + + while(brdshm->uptime < brdshm->touchtime) + {reload_bcache();} + numboards = brdshm->number; +} + +void touch_boards() { + time(&(brdshm->touchtime)); + numboards = -1; + resolve_boards(); +} +void addbrd_touchcache() +{ + brdshm->number++; + numboards=brdshm->number; + reset_board(numboards); +} +#if !defined(_BBS_UTIL_C_) +void reset_board(int bid) { /* Ptt: �o�˴N���ΦѬOtouch board�F */ + int fd,i; + boardheader_t *bhdr; + + if(--bid < 0) + return; + if(brdshm->busystate) { + safe_sleep(1); + } else { + brdshm->busystate = 1; + 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); + } + sort_bcache(); + for(i=0;i<brdshm->number;i++) + { + bcache[i].firstchild[0]=NULL; + bcache[i].firstchild[1]=NULL; + } + brdshm->busystate = 0; + } +} + +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) && Ben_Perm(bhdr) && + (*func)(bhdr) == QUIT) + return QUIT; + } + return 0; +} +#endif + +boardheader_t *getbcache(int bid) { /* Ptt��g */ + return bcache + bid - 1; +} +int getbtotal(int bid) +{ + return brdshm->total[bid - 1]; +} +void setbtotal(int bid) { + boardheader_t *bh = getbcache(bid); + struct stat st; + char genbuf[256]; + int num,fd; + + sprintf(genbuf, "boards/%s/.DIR", bh->brdname); + + if((fd = open(genbuf, O_RDWR)) < 0) + return; /* .DIR���F */ + fstat(fd, &st); + num = st.st_size / sizeof(fileheader_t); + brdshm->total[bid - 1] = num; + + if(num>0) + { + lseek(fd, (off_t) (num - 1) * sizeof(fileheader_t), SEEK_SET); + if(read(fd, genbuf, FNLEN)>=0) + { + brdshm->lastposttime[bid - 1]=(time_t) atoi(&genbuf[2]); + } + } + else + brdshm->lastposttime[bid - 1] = 0; + close(fd); + if(num) + touchdircache(bid); +} + +void +touchbpostnum(int bid, int delta) { + int *total = &brdshm->total[bid - 1]; + if (*total) *total += delta; +} + + +int getbnum(char *bname) { + register int i=0, j, start = 0, end = brdshm->number - 1; + register boardheader_t **bhdr; + bhdr=brdshm->sorted[0]; + for(i=((start+end)/2); ;i=(start+end)/2) + { + if(! (j=strcasecmp(bname,bhdr[i]->brdname))) + return (int) (bhdr[i] - bcache +1); + if(end==start) + { + break; + } + else if(i==start) + { + i=end; + start=end; + } + else if(j>0) start = i; + else end = i; + } + return 0; +} + +#if !defined(_BBS_UTIL_C_) +extern char *fn_water; +extern char *str_sysop; + +int haspostperm(char *bname) { + register int i; + char buf[200]; + + setbfile(buf, bname, fn_water); + if(belong(buf, cuser.userid)) + return 0; + + if(!strcasecmp(bname, DEFAULT_BOARD)) + return 1; + + if (!strcasecmp(bname, "PttLaw")) + return 1; + + if(!HAS_PERM(PERM_POST)) + return 0; + + if(!(i = getbnum(bname))) + return 0; + + /* ���K�ݪO�S�O�B�z */ + if(bcache[i - 1].brdattr & BRD_HIDE) + return 1; + + i = bcache[i - 1].level; + + if (HAS_PERM(PERM_VIOLATELAW) && (i & PERM_VIOLATELAW)) + return 1; + else if (HAS_PERM(PERM_VIOLATELAW)) + return 0; + + return HAS_PERM(i & ~PERM_POST); +} +#endif + +/*-------------------------------------------------------*/ +/* PTT cache */ +/*-------------------------------------------------------*/ +/* cachefor �ʺA�ݪ� */ +struct pttcache_t *ptt; + +static void reload_pttcache() { + if(ptt->busystate) + safe_sleep(1); + else { /* jochang: temporary workaround */ + fileheader_t item, subitem; + char pbuf[256], buf[256], *chr; + FILE *fp, *fp1, *fp2; + int id, section = 0; + + ptt->busystate = 1; + ptt->max_film = 0; + bzero(ptt->notes, sizeof ptt->notes); + setapath(pbuf, "Note"); + setadir(buf, pbuf); + id = 0; + if((fp = fopen(buf, "r"))) { + while(fread(&item, sizeof(item), 1, fp)) { + if(item.title[3]=='<' && item.title[8]=='>') { + sprintf(buf,"%s/%s", pbuf, item.filename); + setadir(buf, buf); + if(!(fp1 = fopen(buf, "r"))) + continue; + ptt->next_refresh[section] = ptt->n_notes[section] = id; + section ++; + while(fread(&subitem, sizeof(subitem), 1, fp1)) { + sprintf(buf,"%s/%s/%s", pbuf, item.filename , + subitem.filename); + if(!(fp2=fopen(buf,"r"))) + continue; + fread(ptt->notes[id],sizeof(char), 200*11, fp2); + ptt->notes[id][200*11 - 1]=0; + id++; + fclose(fp2); + if(id >= MAX_MOVIE) + break; + } + fclose(fp1); + if(id >= MAX_MOVIE || section >= MAX_MOVIE_SECTION) + break; + } + } + fclose(fp); + } + ptt->next_refresh[section] = -1; + ptt->n_notes[section] = ptt->max_film = id-1; + ptt->max_history = ptt->max_film - 2; + if(ptt->max_history > MAX_HISTORY - 1) + ptt->max_history = MAX_HISTORY - 1; + if(ptt->max_history <0) ptt->max_history=0; + + fp = fopen("etc/today_is","r"); + if(fp) { + fgets(ptt->today_is,15,fp); + if((chr = strchr(ptt->today_is,'\n'))) + *chr = 0; + ptt->today_is[15] = 0; + fclose(fp); + } + + /* ���Ҧ���Ƨ�s��A�]�w uptime */ + + ptt->uptime = ptt->touchtime ; +#if !defined(_BBS_UTIL_C_) + log_usies("CACHE", "reload pttcache"); +#endif + ptt->busystate = 0; + } +} + +void resolve_garbage() { + int count=0; + + if(ptt == NULL) { + ptt = attach_shm(PTTSHM_KEY, sizeof(*ptt)); + if(ptt->touchtime == 0) + ptt->touchtime = 1; + } + while(ptt->uptime < ptt->touchtime) { /* ����while�� */ + reload_pttcache(); + if(count ++ > 10 && ptt->busystate) { +/* Ptt: �o��|�����D load�W�L10 ���|�Ҧ��iloop��process���� busystate = 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 +*/ + ptt->busystate = 0; +#ifndef _BBS_UTIL_C_ + log_usies("CACHE", "refork Ptt dead lock"); +#endif + } + } +} + +/*-------------------------------------------------------*/ +/* PTT's cache */ +/*-------------------------------------------------------*/ +/* cachefor from host �P�̦h�W�u�H�� */ +struct fromcache_t *fcache; + +static void reload_fcache() { + if(fcache->busystate) + safe_sleep(1); + else { + FILE *fp; + + fcache->busystate = 1; + bzero(fcache->domain, sizeof fcache->domain); + if((fp = fopen("etc/domain_name_query","r"))) { + char buf[256],*po; + + fcache->top=0; + while(fgets(buf, sizeof(buf),fp)) { + if(buf[0] && buf[0] != '#' && buf[0] != ' ' && + buf[0] != '\n') { + sscanf(buf,"%s",fcache->domain[fcache->top]); + po = buf + strlen(fcache->domain[fcache->top]); + while(*po == ' ') + po++; + strncpy(fcache->replace[fcache->top],po,49); + fcache->replace[fcache->top] + [strlen(fcache->replace[fcache->top])-1] = 0; + (fcache->top)++; + if(fcache->top == MAX_FROM) + break; + } + } + } + + fcache->max_user=0; + + /* ���Ҧ���Ƨ�s��A�]�w uptime */ + fcache->uptime = fcache->touchtime; +#if !defined(_BBS_UTIL_C_) + log_usies("CACHE", "reload fcache"); +#endif + fcache->busystate = 0; + } +} + +void resolve_fcache() { + if(fcache == NULL) { + fcache = attach_shm(FROMSHM_KEY, sizeof(*fcache)); + if(fcache->touchtime == 0) + fcache->touchtime = 1; + } + while(fcache->uptime < fcache->touchtime) + reload_fcache(); +} + +extern time_t login_start_time; +extern char *fn_visable; +FILE *DEBUG = NULL; + +void hbflreload(int bid) +{ + int hbfl[MAX_FRIEND + 1], i, num, uid; + char buf[128]; + FILE *fp; + + 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("guest", buf) == 0 || + (uid = searchuser(buf)) == 0 ) { + --num; + continue; + } + hbfl[num] = uid; + } + fclose(fp); + } + hbfl[0] = time(NULL); + memcpy(uhash->hbfl[bid], hbfl, sizeof(hbfl)); +} + +int hbflcheck(int bid, int uid) +{ + int i; + + if( uhash->hbfl[bid][0] < login_start_time - HBFLexpire ) + hbflreload(bid); + for( i = 1 ; uhash->hbfl[bid][i] != 0 && i <= MAX_FRIEND ; ++i ){ + if( uhash->hbfl[bid][i] == uid ) + return 0; + } + return 1; +} diff --git a/mbbsd/cal.c b/mbbsd/cal.c new file mode 100644 index 00000000..680ee9d6 --- /dev/null +++ b/mbbsd/cal.c @@ -0,0 +1,512 @@ +/* $Id: cal.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "perm.h" +#include "proto.h" + +extern struct utmpfile_t *utmpshm; +extern int usernum; + +/* ���� Multi play */ +static int count_multiplay(int unmode) { + register int i, j; + register userinfo_t *uentp; + extern struct utmpfile_t *utmpshm; + + for(i = j = 0; i < USHM_SIZE; i++) { + uentp = &(utmpshm->uinfo[i]); + if(uentp->uid == usernum) + if(uentp->lockmode == unmode) + j++; + } + return j; +} + +extern userinfo_t *currutmp; +extern char *ModeTypeTable[]; + +int lockutmpmode(int unmode, int state) { + int errorno = 0; + + if(currutmp->lockmode) + errorno = 1; + else if(count_multiplay(unmode)) + errorno = 2; + + if(errorno && !(state == LOCK_THIS && errorno == LOCK_MULTI)) { + clear(); + move(10,20); + if(errorno == 1) + 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() { + currutmp->lockmode = 0; + return 0; +} + +extern userec_t cuser; +extern userec_t xuser; + +/* �ϥο������ */ +#define VICE_NEW "vice.new" + +/* Heat:�o�� */ +int vice(int money, char* item) { + char buf[128]; + unsigned int viceserial=(currutmp->lastact%1000000)*100+rand()%100; + FILE *fp; + demoney(-money); + sprintf(buf, BBSHOME"/home/%c/%s/%s", + cuser.userid[0], cuser.userid, VICE_NEW); + fp = fopen(buf, "a"); + if(!fp ) + {return 0;} + + fprintf(fp, "%08d\n", viceserial); + fclose(fp); + sprintf(buf, "%s ��F%d$ �s��[%08d]",item, money, viceserial); + mail_id(cuser.userid, buf, "etc/vice.txt", "Ptt�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" +extern char trans_buffer[]; +extern char save_title[]; + +static int osong(char *defaultid) { + char destid[IDLEN + 1],buf[200],genbuf[200],filename[256],say[51]; + char receiver[60],ano[2]; + FILE *fp,*fp1;// *fp2; + fileheader_t mail; + time_t now; + int nsongs; + + now = time(NULL); + strcpy(buf, Cdatedate(&now)); + + lockreturn0(OSONG, LOCK_MULTI); + + /* Jaky �@�H�@���I�@�� */ + if(!strcmp(buf, Cdatedate(&cuser.lastsong)) && !HAS_PERM(PERM_SYSOP)) { + move(22,0); + outs("�A���Ѥw�g�I�L�o�A���ѦA�I�a...."); + refresh(); + pressanykey(); + + unlockutmpmode(); + return 0; + } + + if(cuser.money < 200) { + move(22, 0); + outs("�I�q�n200�ȭ�!...."); + refresh(); + pressanykey(); + unlockutmpmode(); + return 0; + } + move(12, 0); + clrtobot(); + sprintf(buf, "�˷R�� %s �w��Ө�ڮ�۰��I�q�t��\n", cuser.userid); + outs(buf); + trans_buffer[0] = 0; + if(!defaultid){ + getdata(13, 0, "�n�I���֩O:[�i������ Enter ����q]", destid, IDLEN + 1, DOECHO); + while (!destid[0]){ + a_menu("�I�q�q��", SONGBOOK,0 ); + clear(); + getdata(13, 0, "�n�I���֩O:[�i�� Enter ���s��q]", destid, IDLEN + 1, DOECHO); + } + } + else + strcpy(destid,defaultid); + + /* Heat:�I�q�̰ΦW�\�� */ + getdata(14,0, "�n�ΦW��?[y/n]:", ano, 2, DOECHO); + + if(!destid[0]) { + unlockutmpmode(); + return 0; + } + + getdata_str(14, 0, "�Q�n�n��L(�o)��..:", say, 51, DOECHO, "�ڷR�p.."); + sprintf(save_title, "%s:%s", (ano[0]=='y')?"�ΦW��":cuser.userid, say); + getdata_str(16, 0, "�H��֪��H�c(�i��E-mail)?", receiver, 45, + LCECHO, destid); + + + + if (!trans_buffer[0]){ + outs("\n���ۭn��q�o..�i�J�q���n�n����@���q�a..^o^"); + pressanykey(); + a_menu("�I�q�q��", SONGBOOK,0 ); + } + if(!trans_buffer[0] || strstr(trans_buffer, "home") || + strstr(trans_buffer, "boards") || !(fp = fopen(trans_buffer, "r"))) { + unlockutmpmode(); + return 0; + } + + strcpy(filename, OSONGPATH); + + stampfile(filename, &mail); + + unlink(filename); + + if(!(fp1 = fopen(filename, "w"))) { + fclose(fp); + unlockutmpmode(); + return 0; + } + + strcpy(mail.owner, "�I�q��"); + sprintf(mail.title, "�� %s �I�� %s ", (ano[0]=='y')?"�ΦW��":cuser.userid, destid); + mail.savemode = 0; + + while(fgets(buf, 200, fp)) { + char *po; + if(!strncmp(buf, "���D: ", 6)) { + clear(); + move(10,10);prints("%s", buf); + pressanykey(); + fclose(fp); + unlockutmpmode(); + return 0; + } + while((po = strstr(buf, "<~Src~>"))) { + po[0] = 0; + sprintf(genbuf,"%s%s%s",buf,(ano[0]=='y')?"�ΦW��":cuser.userid,po+7); + strcpy(buf,genbuf); + } + while((po = strstr(buf, "<~Des~>"))) { + po[0] = 0; + sprintf(genbuf,"%s%s%s",buf,destid,po+7); + strcpy(buf,genbuf); + } + while((po = strstr(buf, "<~Say~>"))) { + po[0] = 0; + sprintf(genbuf,"%s%s%s",buf,say,po+7); + strcpy(buf,genbuf); + } + fputs(buf,fp1); + } + fclose(fp1); + fclose(fp); + +// do_append(OSONGMAIL "/.DIR", &mail2, sizeof(mail2)); + + if(do_append(OSONGPATH "/.DIR", &mail, sizeof(mail)) != -1) { + cuser.lastsong = time(NULL); + /* Jaky �W�L 500 ���q�N�}�l�� */ + nsongs=get_num_records(OSONGPATH "/.DIR", sizeof(mail)); + if (nsongs > 500){ + delete_range(OSONGPATH "/.DIR", 1, nsongs-500); + } + /* ��Ĥ@������ */ + vice(200, "�I�q"); + } + sprintf(save_title, "%s:%s", (ano[0]=='y')?"�ΦW��":cuser.userid, say); + hold_mail(filename, destid); + + if(receiver[0]) { +#ifndef USE_BSMTP + bbs_sendmail(filename, save_title, receiver); +#else + bsmtp(filename, save_title, receiver,0); +#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() { + osong(NULL); + return 0; +} + +static int inmailbox(int m) { + passwd_query(usernum, &xuser); + cuser.exmailbox = xuser.exmailbox + m; + passwd_update(usernum, &cuser); + return cuser.exmailbox; +} + + +extern int b_lines; + +#if !HAVE_FREECLOAK +/* ������ */ +int p_cloak() { + char buf[4]; + getdata(b_lines-1, 0, + currutmp->invisible ? "�T�w�n�{��?[y/N]" : "�T�w�n����?[y/N]", + buf, 3, LCECHO); + if(buf[0] != 'y') + return 0; + if(cuser.money >= 19) { + vice(19, "cloak"); + currutmp->invisible %= 2; + outs((currutmp->invisible ^= 1) ? MSG_CLOAKED : MSG_UNCLOAK); + refresh(); + safe_sleep(1); + } + return 0; +} +#endif + +int p_from() { + char ans[4]; + + getdata(b_lines-2, 0, "�T�w�n��G�m?[y/N]", ans, 3, LCECHO); + if(ans[0] != 'y') + return 0; + reload_money(); + if(cuser.money < 49) + return 0; + if(getdata_buf(b_lines-1, 0, "�п�J�s�G�m:", + currutmp->from, 17, DOECHO)) { + vice(49,"home"); + currutmp->from_alias=0; + } + return 0; +} + +int p_exmail() { + char ans[4],buf[200]; + int n; + + if(cuser.exmailbox >= MAX_EXKEEPMAIL) { + sprintf(buf,"�e�q�̦h�W�[ %d �ʡA����A�R�F�C", MAX_EXKEEPMAIL); + outs(buf); + refresh(); + return 0; + } + sprintf(buf,"�z���W�� %d �ʮe�q�A�٭n�A�R�h��?", + cuser.exmailbox); + + getdata_str(b_lines-2, 0, buf, ans, 3, LCECHO, "10"); + + n = atoi(ans); + if(!ans[0] || !n) + return 0; + if(n + cuser.exmailbox > MAX_EXKEEPMAIL) + n = MAX_EXKEEPMAIL - cuser.exmailbox; + reload_money(); + if(cuser.money < n * 1000) + return 0; + vice(n * 1000, "mail"); + inmailbox(n); + return 0; +} + +void mail_redenvelop(char* from, char* to, int money, char mode){ + char genbuf[200]; + fileheader_t fhdr; + time_t now; + FILE* fp; + sprintf(genbuf, "home/%c/%s", to[0], to); + stampfile(genbuf, &fhdr); + if (!(fp = fopen(genbuf, "w"))) + return; + now = time(NULL); + fprintf(fp, "�@��: %s\n" + "���D: �۰]�i�_\n" + "�ɶ�: %s\n" + "\033[1;33m�˷R�� %s �G\n\n\033[m" + "\033[1;31m �ڥ]���A�@�� %d �����j���]�� ^_^\n\n" + " §�����N���A�Я���...... ^_^\033[m\n" + , from, ctime(&now), to, money); + fclose(fp); + sprintf(fhdr.title, "�۰]�i�_"); + strcpy(fhdr.owner, from); + + if (mode == 'y') + vedit(genbuf, NA, NULL); + sprintf(genbuf, "home/%c/%s/.DIR", to[0], to); + append_record(genbuf, &fhdr, sizeof(fhdr)); +} + +int p_give() { + int money; + char id[IDLEN + 1], genbuf[90]; + time_t now = time(0); + + move(1,0); + usercomplete("�o�쩯�B�id:", id); + if(!id[0] || !strcmp(cuser.userid,id) || + !getdata(2, 0, "�n���h�ֿ�:", genbuf, 7, LCECHO)) + return 0; + money = atoi(genbuf); + reload_money(); + if(money > 0 && cuser.money >= money ) { + deumoney(searchuser(id), money); + demoney(-money); + now = time(NULL); + sprintf(genbuf,"%s\t��%s\t%d\t%s", cuser.userid, id, money, + ctime(&now)); + log_file(FN_MONEY, genbuf); + genbuf[0] = 'n'; + getdata(3, 0, "�n�ۦ�Ѽg���]�U�ܡH[y/N]", genbuf, 2, LCECHO); + mail_redenvelop(cuser.userid, id, money, genbuf[0]); + } + return 0; +} + +int p_sysinfo() { + char buf[100]; + long int total,used; + float p; + + move(b_lines-1,0); + clrtoeol(); + cpuload(buf); + outs("CPU �t�� : "); + outs(buf); + + p = swapused(&total,&used); + sprintf(buf, " �����O����: %.1f%%(����:%ldMB �α�:%ldMB)\n", + p*100, total >> 20, used >> 20); + outs(buf); + pressanykey(); + return 0; +} + +/* �p�p��� */ +static void ccount(float *a, float b, int cmode) { + switch(cmode) { + case 0: + case 1: + case 2: + *a += b; + break; + case 3: + *a -= b; + break; + case 4: + *a *= b; + break; + case 5: + *a /= b; + break; + } +} + +int cal() { + float a = 0; + char flo = 0, ch = 0; + char mode[6] = {' ','=','+','-','*','/'} , cmode = 0; + char buf[100] = "[ 0] [ ] ", b[20] = "0"; + + move(b_lines - 1, 0); + clrtoeol(); + outs(buf); + move(b_lines, 0); + clrtoeol(); + outs("\033[44m �p�p��� \033[31;47m (0123456789+-*/=) " + "\033[30m��J \033[31m " + "(Q)\033[30m ���} \033[m"); + while(1) { + ch = igetch(); + switch(ch) { + case '\r': + ch = '='; + case '=': + case '+': + case '-': + case '*': + case '/': + ccount(&a, atof(b), cmode); + flo = 0; + b[0] = '0'; + b[1] = 0; + move(b_lines - 1, 0); + sprintf(buf, "[%13.2f] [%c] ", a, ch); + outs(buf); + break; + case '.': + if(!flo) + flo = 1; + else + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '0': + if(strlen(b) > 13) + break; + if(flo || b[0] != '0') + sprintf(b,"%s%c",b,ch); + else + b[0]=ch; + move(b_lines - 1, 0); + sprintf(buf, "[%13s] [%c]", b, mode[(int)cmode]); + outs(buf); + break; + case 'q': + return 0; + } + + switch(ch) { + case '=': + a = 0; + cmode = 0; + break; + case '+': + cmode = 2; + break; + case '-': + cmode = 3; + break; + case '*': + cmode = 4; + break; + case '/': + cmode = 5; + break; + } + } +} diff --git a/mbbsd/calendar.c b/mbbsd/calendar.c new file mode 100644 index 00000000..78ca46cf --- /dev/null +++ b/mbbsd/calendar.c @@ -0,0 +1,284 @@ +/* $Id: calendar.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "proto.h" +#include "modes.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) { + static int day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + return leap && m == 2 ? 29 : day[m - 1]; +} + +static int IsLeap(int y) { + if(y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) + return 1; + else + return 0; +} + +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, IsLeap(y)); + return w; +} + +static int ParseDate(char *date, event_t *t) { + char *y, *m, *d; + + y = strtok(date, "/"); + m = strtok(NULL, "/"); + d = strtok(NULL, ""); + if(!y || !m || !d) + return 1; + + t->year = atoi(y); + t->month = atoi(m); + t->day = atoi(d); + if(t->year < 1 || t->month < 1 || t->month > 12 || + t->day < 1 || t->day > 31) + return 1; + t->days = Days(t->year, t->month, t->day); + return 0; +} + +static int ParseColor(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; 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); + e = n; + } +} + +extern userec_t cuser; + +static event_t *ReadEvent(int today) { + FILE *fp; + char buf[256]; + static event_t head; + + head.next = NULL; + setcalfile(buf, cuser.userid); + fp = fopen(buf, "r"); + if(fp) { + while(fgets(buf, sizeof(buf), fp)) { + char *date, *color, *content; + event_t *t; + + if(buf[0] == '#') + continue; + + date = strtok(buf, " \t\n"); + color = strtok(NULL, " \t\n"); + content = strtok(NULL, "\n"); + if(!date || !color || !content) + continue; + + t = malloc(sizeof(event_t)); + if(ParseDate(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 "\33[0;30;47m" +#define HEADER_COLOR "\33[1;44m" +#define HEADER_SUNDAY_COLOR "\33[31m" +#define HEADER_DAY_COLOR "\33[33m" + +static int GenerateCalendar(char **buf, int y, int m, int today, event_t *e) { + static char *week_str[7] = {"��", "�@", "�G", "�T", "�|", "��", "��"}; + static char *month_color[12] = { + "\33[1;32m", "\33[1;33m", "\33[1;35m", "\33[1;36m", + "\33[1;32m", "\33[1;33m", "\33[1;35m", "\33[1;36m", + "\33[1;32m", "\33[1;33m", "\33[1;35m", "\33[1;36m" + }; + static 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, "\33[m"); + + /* 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, IsLeap(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, "\33[1;%dm", e->color); + attr2 = CALENDAR_COLOR; + e = e->next; + } + if(today == first_day + i - 1) { + strcpy(attr1, "\33[1;37;42m"); + attr2 = CALENDAR_COLOR; + } + p += sprintf(p, "%s%2d%s", attr1, i, attr2); + + if(w == 6) { + p += sprintf(p, "\33[m"); + 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, "\33[m"); + } + return line + 1; +} + +int calendar() { + char **buf; + time_t t; + struct tm now; + int i, y, m, today, lines = 0; + event_t *head = NULL, *e = NULL; + + /* initialize date */ + time(&t); + memcpy(&now, localtime(&t), sizeof(struct tm)); + today = Days(now.tm_year + 1900, now.tm_mon + 1, now.tm_mday); + y = now.tm_year + 1900, m = now.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\33[1;37m�{�b�O %d.%02d.%02d %2d:%02d:%02d%cm\33[m", + now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, + (now.tm_hour == 0 || now.tm_hour == 12) ? + 12 : now.tm_hour % 12, now.tm_min, now.tm_sec, + now.tm_hour >= 12 ? 'p' : 'a'); + } else if(i >= 2 && e) { + prints("\t\33[1;37m(\33[%dm%3d\33[37m)\33[m %02d/%02d %s", + e->color, e->days - today, + e->month, e->day, e->content); + e = e->next; + } + outc('\n'); + } + FreeEvent(head); + FreeCalBuffer(buf); + pressanykey(); + return 0; +} diff --git a/mbbsd/card.c b/mbbsd/card.c new file mode 100644 index 00000000..cfa10b0c --- /dev/null +++ b/mbbsd/card.c @@ -0,0 +1,625 @@ +/* $Id: card.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" +extern int usernum; + +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; +} + +/* 0 Spare , 1 heart , ...3 dimon */ +static int card_flower(int card) { + return (card / 13); +} + +/* 1...13 */ +static int card_number(int card) { + return (card % 13 + 1); +} + +static int card_select(int *now) { + char *cc[2] = {"\033[44m \033[m", + "\033[1;33;41m �� \033[m"}; + + 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(egetch()) { + 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, int flower, int show) { + int color = 31; + char *cn[13] = {"��", "��", "��", "��", "��", "��", + "��", "��", "��", "10", "��", "��", "��"}; + if(flower == 0 || flower == 3) + color = 36; + if((show < 0) && (cline > 1 && cline < 8)) + prints("�x\033[1;33;42m��������\033[m�x"); + else + switch(cline) { + case 1: + prints("�~�w�w�w�w��"); + break; + case 2: + prints("�x\033[1;%dm%s\033[m �x", color, cn[number - 1]); + break; + case 3: + if(flower == 1) + prints("�x\033[1;%dm��������\033[m�x", color); + else + prints("�x\033[1;%dm ���� \033[m�x", color); + break; + case 4: + if(flower == 1) + prints("�x\033[1;%dm�i�i�i�i\033[m�x", color); + else if (flower == 3) + prints("�x\033[1;%dm���i�i��\033[m�x", color); + else + prints("�x\033[1;%dm���i�i��\033[m�x", color); + break; + case 5: + if(flower == 0) + prints("�x\033[1;%dm�i�i�i�i\033[m�x", color); + else if (flower == 3) + prints("�x\033[1;%dm�i�����i\033[m�x", color); + else + prints("�x\033[1;%dm���i�i��\033[m�x", color); + break; + case 6: + if(flower == 0) + prints("�x\033[1;%dm ���� \033[m�x", color); + else if (flower == 3) + prints("�x\033[1;%dm��������\033[m�x", color); + else + prints("�x\033[1;%dm ���� \033[m�x", color); + break; + case 7: + prints("�x \033[1;%dm%s\033[m�x", color, cn[number - 1]); + break; + case 8: + prints("���w�w�w�w��"); + break; + } +} + +static void card_show(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 < 5 && 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 < 5 && 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, error; + for(error=0, i=rand()%52; cards[i] == 1 && error<52; error++, i=rand()%52); + if(error==52) card_new(cards); // Ptt:�o�䦳dead lock���D + cards[i] = 1; + return i; +} + +static void card_start(char name[]) { + clear(); + stand_title(name); + move(1, 0); + prints(" \033[1;33;41m �q �� \033[m"); + move(10, 0); + prints("\033[1;34;44m���㡻�㡻�㡻�㡻�㡻�㡻�㡻�㡻�㡻�㡻�㡻��" + "���㡻�㡻�㡻�㡻�㡻�㡻�㡻\033[m"); + move(19, 0); + prints(" \033[1;37;42m �� �v \033[m"); +} + +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() { + int i, j, turn; + int cpu[5], c[5], me[5], m[5]; + int cards[52]; + int count = 0; + char *ff[4] = {"\033[1;36m�®�", "\033[1;31m����", + "\033[1;31m���", "\033[1;36m�ª�"}; + 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(cpu, c, me, m); + j = 0; + turn = 1; + move(21, 0); + clrtoeol(); + prints("[0]�ثe %d , �� %d �I\n", count, 99 - count); + prints("���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\033[m �ثe \033[1;31m%d/\033[34m%d\033[m �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(cpu, c, me, m); + pressanykey(); + if(count > 99) { + move(22, 0); + clrtoeol(); + prints("[%d]���G..YOU LOSS..�ثe \033[1;31m%d/\033[34m%d\033[m �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\033[m �ثe \033[1;31m%d/\033[34m%d\033[m �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 \033[1;31m%d/\033[34m%d\033[m �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*/ + +extern userec_t cuser; + +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; + } + return 0; +} + +static int card_double_ask() { + char buf[100], buf2[3]; + + sprintf(buf, "[ %s ]�z�{�b�@�� %d P��, �{�b�n����(�[�� %d ��)��? [y/N]", + cuser.userid, cuser.money, JACK); + reload_money(); + if(cuser.money < JACK) + return 0; + getdata(20, 0, buf, buf2, 2, LCECHO); + if(buf2[0] == 'y' || buf2[0] == 'Y') + return 1; + return 0; +} + +static int card_ask() { + char buf[100], buf2[3]; + + sprintf(buf, "[ %s ]�z�{�b�@�� %d P��, �٭n�[�P��? [y/N]", + cuser.userid, cuser.money); + getdata(20, 0 , buf, buf2, 2, 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 < 5 && 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 < 5 && all[i] >= 0 && count <= 11; i++) + if (card_number(all[i]) == 1) + count += 10; + return count; +} + +extern int b_lines; + +static int card_jack(int *db) { + int i, j; + int cpu[5], c[5], me[5], m[5]; + int cards[52]; + + for(i = 0;i<5;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_start("�³ǧJDOUBLE�l�[��"); + cpu[0] = card_give(cards); + cpu[1] = card_give(cards); + me[0] = *db; + me[1] = card_give(cards); + } + c[1] = m[0] = m[1] = 1; + card_show(cpu, c, me, m); + if((card_number(me[0]) == 0 && card_number(me[1]) == 12) || + (card_number(me[1]) == 0 && card_number(me[0]) == 12)) { + if(card_flower(me[0]) == 0 && card_flower(me[1]) == 0) { + move(b_lines - 1, 0); + prints("�D�`������! (�W�Ŷ³ǧJ!! �[ %d ��)", JACK * 10); + game_log(JACK, JACK * 10); + pressanykey(); + return 0; + } else { + move(b_lines - 1, 0); + prints("�ܤ�����! (�³ǧJ!! �[ %d ��)", JACK * 5); + game_log(JACK, JACK * 5); + pressanykey(); + return 0; + } + } + if((card_number(cpu[0]) == 0 && card_number(cpu[1]) == 12) || + (card_number(cpu[1]) == 0 && card_number(cpu[0]) == 12)) { + c[0] = 1; + card_show(cpu, c, me, m); + move(b_lines - 1, 0); + prints("�K�K...���n�N��....�³ǧJ!!"); + game_log(JACK, 0); + pressanykey(); + return 0; + } + if((*db < 0)&& (card_number(me[0]) == card_number(me[1])) && + (card_double_ask())) { + *db = me[1]; + me[1] = card_give(cards); + card_show(cpu, c, me, m); + } + i = 2; + while(i < 5 && card_ask()) { + me[i] = card_give(cards); + m[i] = 1; + card_show(cpu, c, me, m); + if(card_alls_lower(me) > 21) { + move(b_lines - 1, 0); + prints("���...�z���F!"); + game_log(JACK, 0); + pressanykey(); + return 0; + } + i++; + if((i == 3) && (card_number(me[0]) == 7) && + (card_number(me[1]) == 7) && (card_number(me[2]) == 7)) { + move(b_lines - 1, 0); + prints("�ܤ�����! (���B�C��!! �[ %d ��)", JACK * 7); + game_log(JACK, JACK * 7); + pressanykey(); + return 0; + } + } + if(i == 5) {/*�L����*/ + move(b_lines - 1, 0); + prints("�n�F�`��! �L������! �[P�� %d ��!", 5 * JACK); + game_log(JACK, JACK * 5); + pressanykey(); + return 0; + } + j = 2; + c[0] = 1; + while((card_alls_upper(cpu) < card_alls_upper(me))|| + ((card_alls_upper(cpu) == card_alls_upper(me) && j < i ) && j < 5)) { + cpu[j] = card_give(cards); + c[j] = 1; + if(card_alls_lower(cpu) > 21) { + card_show(cpu, c, me, m); + move(b_lines - 1, 0); + prints("����...�q���z���F! �AĹ�F! �i�oP�� %d ��", JACK * 2); + game_log(JACK, JACK * 2); + pressanykey(); + return 0; + } + j++; + } + card_show(cpu, c, me, m); + move(b_lines - 1, 0); + prints("�z�z...�q��Ĺ�F!"); + game_log(JACK, 0); + pressanykey(); + return 0; +} + +int g_card_jack() { + 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�w�n���³ǧJ�� �@���Q����?(Y/N)?[N]", + buf, 3, LCECHO); + if((*buf != 'y') && (*buf != 'Y')) + break; + else { + db = -1; + vice(PMONEY, "�³ǧJ"); + card_jack(&db); + if(db >= 0) + card_jack(&db); + } + } + 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() { + 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(cpu, c, me, m); + i = 1; + while(i < 5 && card_ask()) { + me[i] = card_give(cards); + m[i] = 1; + card_show(cpu, c, me, m); + if(card_all(me) > 21) { + move(b_lines - 1, 0); + prints("���...�z���F!"); + game_log(TEN_HALF, 0); + pressanykey(); + return 0; + } + i++; + } + if(i == 5) {/*�L����*/ + move(b_lines - 1, 0); + prints("�n�F�`��! �L������! �[P�� %d ��!", 5 * PMONEY); + game_log(TEN_HALF, PMONEY * 5); + pressanykey(); + 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(cpu, c, me, m); + move(b_lines - 1, 0); + prints("����...�q���z���F! �AĹ�F! �i�oP�� %d ��", PMONEY * 2); + game_log(TEN_HALF, PMONEY * 2); + pressanykey(); + return 0; + } + j++; + } + card_show(cpu, c, me, m); + move(b_lines - 1, 0); + prints("�z�z...�q��Ĺ�F!"); + game_log(TEN_HALF, 0); + pressanykey(); + return 0; +} + +int g_ten_helf() { + char buf[3]; + + setutmpmode(TENHALF); + while(1) { + reload_money(); + if(cuser.money < TEN_HALF) { + outs("�z����������!�h�h�o���Ǧ��N�q���峹�A��~~~"); + return 0; + } + getdata(b_lines - 1, 0, + "\033[1;37m�T�w�n���Q�I�b�� �@���Q����?(Y/N)?[N]\033[m", + 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 new file mode 100644 index 00000000..f75383a8 --- /dev/null +++ b/mbbsd/chat.c @@ -0,0 +1,623 @@ +/* $Id: chat.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <ctype.h> +#include <netdb.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern userinfo_t *currutmp; +static int chatline; +static int stop_line; /* next line of bottom of message window area */ +static FILE *flog; + +static void printchatline(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); +} + +extern int b_lines; /* Screen bottom line number: t_lines-1 */ + +static void chat_clear() { + 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(char *chatid) { + move(b_lines - 1, 0); + clrtoeol(); + outs(chatid); + outc(':'); +} + +static int chat_send(int fd, char *buf) { + int len; + char genbuf[200]; + + sprintf(genbuf, "%s\n", buf); + len = strlen(genbuf); + return (send(fd, genbuf, len, 0) == len); +} + +static char chatroom[IDLEN]; /* Chat-Room Name */ + +static int chat_recv(int fd, char *chatid) { + static char buf[512]; + static int bufstart = 0; + char genbuf[200]; + int c, len; + char *bptr; + + len = sizeof(buf) - bufstart - 1; + if((c = recv(fd, buf + bufstart, len, 0)) <= 0) + return -1; + c += bufstart; + + bptr = buf; + while(c > 0) { + len = strlen(bptr) + 1; + if(len > c && len < (sizeof buf / 2)) + break; + + if(*bptr == '/') { + switch(bptr[1]) { + case 'c': + chat_clear(); + break; + case 'n': + strncpy(chatid, bptr + 2, 8); + print_chatid(chatid); + clrtoeol(); + break; + case 'r': + strncpy(chatroom, bptr + 2, IDLEN - 1); + break; + case 't': + move(0, 0); + clrtoeol(); + sprintf(genbuf, "�ͤѫ� [%s]", chatroom); + prints("\033[1;37;46m %-21s \033[45m ���D�G%-48s\033[m", + genbuf, bptr + 2); + } + } else + printchatline(bptr); + + c -= len; + bptr += len; + } + + if(c > 0) { + strcpy(genbuf, bptr); + strcpy(buf, genbuf); + bufstart = len - 1; + } else + bufstart = 0; + return 0; +} + +extern userec_t cuser; + +static int printuserent(userinfo_t *uentp) { + static char uline[80]; + static int cnt; + char pline[30]; + + if(!uentp) { + if(cnt) + printchatline(uline); + bzero(uline, 80); + cnt = 0; + return 0; + } + if(!HAS_PERM(PERM_SYSOP) && !HAS_PERM(PERM_SEECLOAK) && uentp->invisible) + return 0; + + sprintf(pline, "%-13s%c%-10s ", uentp->userid, + uentp->invisible ? '#' : ' ', + modestring(uentp, 1)); + if(cnt < 2) + strcat(pline, "�x"); + strcat(uline, pline); + if(++cnt == 3) { + printchatline(uline); + memset(uline, 0, 80); + cnt = 0; + } + return 0; +} + +static void chathelp(char *cmd, char *desc) { + char buf[STRLEN]; + + sprintf(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", "MUD-like ����ʵ�"); + chathelp("[/.]help", "chicken �����Ϋ��O"); + chathelp("[/h]elp op", "�ͤѫǺz���M�Ϋ��O"); + 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", "�d�ߺ���"); + chathelp("[/r]oom", "�C�X�@��ͤѫ�"); + chathelp("[/u]sers", "�C�X���W�ϥΪ�"); + chathelp("[/w]ho", "�C�X���ͤѫǨϥΪ�"); + chathelp("[/w]hoin <room>", "�C�X�ͤѫ�<room> ���ϥΪ�"); + } +} + +static void chat_date() { + time_t thetime; + char genbuf[200]; + + time(&thetime); + sprintf(genbuf, "�� " BBSNAME "�зǮɶ�: %s", Cdate(&thetime)); + printchatline(genbuf); +} + +static void chat_pager() { + char genbuf[200]; + + char *msgs[] = {"����", "���}", "�ޱ�", "����","�n��"}; + sprintf(genbuf, "�� �z���I�s��:[%s]", + msgs[currutmp->pager = (currutmp->pager+1)%5]); + printchatline(genbuf); +} + +extern char *str_space; +extern userec_t xuser; +extern char *fn_plans; +extern char *err_uid; + +static void chat_query(char *arg) { + char *uid; + int tuid; + + printchatline(""); + strtok(arg, str_space); + if((uid = strtok(NULL, str_space)) && (tuid = getuser(uid))) { + char buf[128], *ptr; + FILE *fp; + + sprintf(buf, "%s(%s) �@�W�� %d ���A�o���L %d �g�峹", + xuser.userid, xuser.username, xuser.numlogins, xuser.numposts); + printchatline(buf); + + sprintf(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); +} + +extern char *msg_shortulist; + +static void chat_users() { + printchatline(""); + printchatline("�i " BBSNAME "���C�ȦC�� �j"); + printchatline(msg_shortulist); + + if(apply_ulist(printuserent) == -1) + printchatline("�ŵL�@�H"); + printuserent(NULL); +} + +typedef struct chat_command_t { + char *cmdname; /* Chatroom command length */ + void (*cmdfunc) (); /* Pointer to function */ +} chat_command_t; + +static chat_command_t chat_cmdtbl[] = { + {"help", chat_help}, + {"clear", chat_clear}, + {"date", chat_date}, + {"pager", chat_pager}, + {"query", chat_query}, + {"users", chat_users}, + {NULL, NULL} +}; + +static int chat_cmd_match(char *buf, char *str) { + while(*str && *buf && !isspace(*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; +} + +extern char trans_buffer[256]; /* �@��ǻ��ܼ� add by Ptt */ + +#if 0 +static char *select_address() { + int c; + FILE *fp; + char nametab[25][90]; + char iptab[25][18], buf[80]; + + move(1, 0); + clrtobot(); + outs("\n \033[36m�i��Ӧa����b�a!�j\033[m " + "�� �i�H�U�������n�O���ת����ӡj \n"); + trans_buffer[0]=0; + if((fp = fopen("etc/teashop", "r"))) { + for(c = 0; fscanf(fp, "%s%s", iptab[c], nametab[c]) != EOF; c++) { + sprintf(buf,"\n (\033[36m%d\033[0m) %-30s [%s]", + c + 1, nametab[c], iptab[c]); + outs(buf); + } + getdata(20, 10, "��\033[32m �п�ܡA[0]���}�G\033[0m", buf, 3, + LCECHO); + if(buf[1]) + buf[0] = (buf[0] + 1) * 10 + (buf[1] - '1'); + else + buf[0] -= '1'; + if(buf[0] >= 0 && buf[0] < c) + strcpy(trans_buffer,iptab[(int)buf[0]]); + } else { + outs("�����S���n�O����X�����"); + pressanykey(); + } + return trans_buffer; +} +#endif + +extern int usernum; +extern int t_lines; +extern char *msg_seperator; +#define MAXLASTCMD 6 +static int chatid_len = 10; + +int t_chat() { + char inbuf[80], chatid[20], lastcmd[MAXLASTCMD][80], *ptr = ""; + struct sockaddr_in sin; + struct hostent *h; + int cfd, cmdpos, ch; + int currchar; + int newmail; + int chatting = YEA; + char fpath[80]; + char genbuf[200]; + char roomtype; + + if(inbuf[0] == 0) + return -1; + + outs(" �X���e�� �б��........ "); + if(!(h = gethostbyname("localhost"))) { + perror("gethostbyname"); + return -1; + } + memset(&sin, 0, sizeof sin); +#ifdef FreeBSD + sin.sin_len = sizeof(sin); +#endif + sin.sin_family = PF_INET; + memcpy(&sin.sin_addr, h->h_addr, h->h_length); + sin.sin_port = htons(NEW_CHATPORT); + cfd = socket(sin.sin_family, SOCK_STREAM, 0); + if(!(connect(cfd, (struct sockaddr *) & sin, sizeof sin))) + roomtype = 1; + else { + sin.sin_port = CHATPORT; + cfd = socket(sin.sin_family, SOCK_STREAM, 0); + if(!(connect(cfd, (struct sockaddr *) & sin, sizeof sin))) + roomtype = 2; + else { + outs("\n " + "�z! �S�H�b����C...�n�����a�誺�H���h�}����!..."); + system("bin/xchatd"); + pressanykey(); + return -1; + } + } + + while(1) { + getdata(b_lines - 1, 0, "�п�J��ѥN���G", inbuf, 9, DOECHO); + sprintf(chatid, "%s", (inbuf[0] ? inbuf : cuser.userid)); + chatid[8] = '\0'; +/* + �®榡: /! �ϥΪ̽s�� �ϥΪ̵��� UserID ChatID + �s�榡: /! UserID ChatID Password +*/ + if(roomtype == 1) + sprintf(inbuf, "/! %s %s %s", + cuser.userid, chatid, cuser.passwd); + else + sprintf(inbuf, "/! %d %d %s %s", + usernum, cuser.userlevel, cuser.userid, chatid); + chat_send(cfd, inbuf); + if(recv(cfd, inbuf, 3, 0) != 3) + 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(); + } + + add_io(cfd, 0); + + newmail = currchar = 0; + cmdpos = -1; + memset(lastcmd, 0, MAXLASTCMD * 80); + + setutmpmode(CHATING); + currutmp->in_chat = YEA; + strcpy(currutmp->chatid, chatid); + + clear(); + chatline = 2; + strcpy(inbuf, chatid); + stop_line = t_lines - 3; + + move(stop_line, 0); + outs(msg_seperator); + move(1, 0); + outs(msg_seperator); + print_chatid(chatid); + memset(inbuf, 0, 80); + + sethomepath(fpath, cuser.userid); + strcpy(fpath, tempnam(fpath, "chat_")); + flog = fopen(fpath, "w"); + + while(chatting) { + move(b_lines - 1, currchar + chatid_len); + ch = igetkey(); + + switch(ch) { + case KEY_DOWN: + cmdpos += MAXLASTCMD - 2; + case KEY_UP: + cmdpos++; + cmdpos %= MAXLASTCMD; + strcpy(inbuf, lastcmd[cmdpos]); + move(b_lines - 1, chatid_len); + clrtoeol(); + outs(inbuf); + currchar = strlen(inbuf); + continue; + case KEY_LEFT: + if(currchar) + --currchar; + continue; + case KEY_RIGHT: + if(inbuf[currchar]) + ++currchar; + continue; + } + + if(!newmail && currutmp->mailalert ) { + newmail = 1; + printchatline("�� ���I�l�t�S�ӤF..."); + } + + if(ch == I_OTHERDATA) { /* incoming */ + if(chat_recv(cfd, chatid) == -1) { + chatting = chat_send(cfd, "/b"); + break; + } + continue; + } + 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++]); + } + continue; + } + + if(ch == '\n' || ch == '\r') { + if(*inbuf) { + 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--) + strcpy(lastcmd[cmdpos], lastcmd[cmdpos - 1]); + strcpy(lastcmd[0], inbuf); + + inbuf[0] = '\0'; + currchar = 0; + cmdpos = -1; + } + print_chatid(chatid); + move(b_lines - 1, chatid_len); + continue; + } + + if(ch == Ctrl('H') || ch == '\177') { + if(currchar) { + currchar--; + inbuf[69] = '\0'; + memcpy(&inbuf[currchar], &inbuf[currchar + 1], 69 - currchar); + move(b_lines - 1, currchar + chatid_len); + clrtoeol(); + outs(&inbuf[currchar]); + } + continue; + } + if(ch == Ctrl('Z') || ch == Ctrl('Y')) { + inbuf[0] = '\0'; + currchar = 0; + print_chatid(chatid); + move(b_lines - 1, chatid_len); + continue; + } + + if(ch == Ctrl('C')) { + chat_send(cfd, "/b"); + break; + } + if(ch == Ctrl('D')) { + if(currchar < strlen(inbuf)) { + inbuf[69] = '\0'; + memcpy(&inbuf[currchar], &inbuf[currchar + 1], 69 - currchar); + move(b_lines - 1, currchar + chatid_len); + clrtoeol(); + outs(&inbuf[currchar]); + } + continue; + } + if(ch == Ctrl('K')) { + inbuf[currchar] = 0; + move(b_lines - 1, currchar + chatid_len); + clrtoeol(); + continue; + } + if(ch == Ctrl('A')) { + currchar = 0; + continue; + } + if(ch == Ctrl('E')) { + currchar = strlen(inbuf); + continue; + } + if(ch == Ctrl('I')) { + extern screenline_t *big_picture; + screenline_t *screen0 = calloc(t_lines, sizeof(screenline_t)); + + memcpy(screen0, big_picture, t_lines * sizeof(screenline_t)); + add_io(0, 0); + t_idle(); + memcpy(big_picture, screen0, t_lines * sizeof(screenline_t)); + free(screen0); + redoscr(); + add_io(cfd, 0); + continue; + } + 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, 4, LCECHO); + if (*ans == 'm') { + fileheader_t mymail; + char title[128]; + + sethomepath(genbuf, cuser.userid); + stampfile(genbuf, &mymail); + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, "[��.��.��]"); + strcpy(mymail.title, "�|ij\033[1;33m�O��\033[m"); + sethomedir(title, cuser.userid); + append_record(title, &mymail, sizeof(mymail)); + Rename(fpath, genbuf); + } else + unlink(fpath); + } + + return 0; +} +/* -------------------------------------------------- */ +#if 0 + +extern char page_requestor[]; +extern userinfo_t *currutmp; + +#endif diff --git a/mbbsd/chc_draw.c b/mbbsd/chc_draw.c new file mode 100644 index 00000000..b3bd216f --- /dev/null +++ b/mbbsd/chc_draw.c @@ -0,0 +1,187 @@ +/* $Id: chc_draw.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +#define SIDE_ROW 10 +#define TURN_ROW 11 +#define STEP_ROW 12 +#define TIME_ROW 13 +#define WARN_ROW 15 +#define MYWIN_ROW 17 +#define HISWIN_ROW 18 + +extern char chc_warnmsg[64], *chc_mateid; +extern rc_t chc_from, chc_to, chc_select; +extern int chc_selected, chc_my, chc_turn, chc_firststep; +extern int chc_lefttime; +extern int chc_hiswin, chc_hislose, chc_histie; + +static char *turn_str[2] = {"�ª�", "����"}; + +static char *num_str[10] = { + "", "�@", "�G", "�T", "�|", "��", "��", "�C", "�K", "�E" +}; + +static char *chess_str[2][8] = { + /* 0 1 2 3 4 5 6 7 */ + {" ", "�N", "�h", "�H", "��", "��", "�]", "��"}, + {" ", "��", "�K", "��", "��", "�X", "��", "�L"} +}; + +static char *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 *hint_str[] = { + " q �{�����}", + " p �n�D�M��", + "��V�� ���ʹC��", + "Enter ���/����" +}; + +void chc_movecur(int r, int c) { + move(r * 2 + 3, c * 4 + 4); +} + +#define BLACK_COLOR "\033[1;36m" +#define RED_COLOR "\033[1;31m" +#define BLACK_REVERSE "\033[1;37;46m" +#define RED_REVERSE "\033[1;37;41m" +#define TURN_COLOR "\033[1;33m" + +static void showstep(board_t board) { + int turn, fc, tc, eatten; + char *dir; + + turn = CHE_O(board[chc_from.r][chc_from.c]); + fc = (turn == (chc_my ^ 1) ? chc_from.c + 1 : 9 - chc_from.c); + tc = (turn == (chc_my ^ 1) ? chc_to.c + 1 : 9 - chc_to.c); + if(chc_from.r == chc_to.r) + dir = "��"; + else { + if(chc_from.c == chc_to.c) + tc = chc_from.r - chc_to.r; + if(tc < 0) tc = -tc; + + if((turn == (chc_my ^ 1) && chc_to.r > chc_from.r) || + (turn == chc_my && chc_to.r < chc_from.r)) + dir = "�i"; + else + dir = "�h"; + } + prints("%s%s%s%s%s", + turn == 0 ? BLACK_COLOR : RED_COLOR, + chess_str[turn][CHE_P(board[chc_from.r][chc_from.c])], + num_str[fc], dir, num_str[tc]); + eatten = board[chc_to.r][chc_to.c]; + if(eatten) + prints("�G %s%s", + CHE_O(eatten) == 0 ? BLACK_COLOR : RED_COLOR, + chess_str[CHE_O(eatten)][CHE_P(eatten)]); + prints("\033[m"); +} + +extern userec_t cuser; + +void chc_drawline(board_t board, int line) { + int i, j; + + move(line, 0); + clrtoeol(); + if(line == 0) { + prints("\033[1;46m �H�ѹ�� \033[45m%30s VS %-30s\033[m", + cuser.userid, chc_mateid); + } else if(line >= 3 && line <= 21) { + outs(" "); + for(i = 0; i < 9; i++) { + j = board[RTL(line)][i]; + if((line & 1) == 1 && j) { + if(chc_selected && + chc_select.r == RTL(line) && chc_select.c == i) + prints("%s%s\033[m", + CHE_O(j) == 0 ? BLACK_REVERSE : RED_REVERSE, + chess_str[CHE_O(j)][CHE_P(j)]); + else + prints("%s%s\033[m", + CHE_O(j) == 0 ? BLACK_COLOR : RED_COLOR, + 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]); + } + outs(" "); + + if(line >= 3 && line < 3 + dim(hint_str)) { + outs(hint_str[line - 3]); + } else if(line == SIDE_ROW) { + prints("\033[1m�A�O%s%s\033[m", + chc_my == 0 ? BLACK_COLOR : RED_COLOR, + turn_str[chc_my]); + } else if(line == TURN_ROW) { + prints("%s%s\033[m", + TURN_COLOR, + chc_my == chc_turn ? "����A�U�ѤF" : "���ݹ��U��"); + } else if(line == STEP_ROW && !chc_firststep) { + showstep(board); + } else if(line == TIME_ROW) { + prints("�Ѿl�ɶ� %d:%02d", chc_lefttime / 60, chc_lefttime % 60); + } else if(line == WARN_ROW) { + outs(chc_warnmsg); + } else if(line == MYWIN_ROW) { + prints("\033[1;33m%12.12s " + "\033[1;31m%2d\033[37m�� " + "\033[34m%2d\033[37m�� " + "\033[36m%2d\033[37m�M\033[m", + cuser.userid, + cuser.chc_win, cuser.chc_lose - 1, cuser.chc_tie); + } else if(line == HISWIN_ROW) { + prints("\033[1;33m%12.12s " + "\033[1;31m%2d\033[37m�� " + "\033[34m%2d\033[37m�� " + "\033[36m%2d\033[37m�M\033[m", + chc_mateid, + chc_hiswin, chc_hislose - 1, chc_histie); + } + } else if(line == 2 || line == 22) { + outs(" "); + if(line == 2) + for(i = 1; i <= 9; i++) + prints("%s ", num_str[i]); + else + for(i = 9; i >= 1; i--) + prints("%s ", num_str[i]); + } +} + +void chc_redraw(board_t board) { + int i; + + for(i = 0; i <= 22; i++) + chc_drawline(board, i); +} diff --git a/mbbsd/chc_net.c b/mbbsd/chc_net.c new file mode 100644 index 00000000..d094d5f2 --- /dev/null +++ b/mbbsd/chc_net.c @@ -0,0 +1,28 @@ +/* $Id: chc_net.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include "config.h" +#include "pttstruct.h" + +extern rc_t chc_from, chc_to; + +typedef struct drc_t { + rc_t from, to; +} drc_t; + +int chc_recvmove(int s) { + drc_t buf; + + if(read(s, &buf, sizeof(buf)) != sizeof(buf)) + return 1; + chc_from = buf.from, chc_to = buf.to; + return 0; +} + +void chc_sendmove(int s) { + drc_t buf; + + buf.from = chc_from, buf.to = chc_to; + write(s, &buf, sizeof(buf)); +} diff --git a/mbbsd/chc_play.c b/mbbsd/chc_play.c new file mode 100644 index 00000000..86c17fbc --- /dev/null +++ b/mbbsd/chc_play.c @@ -0,0 +1,277 @@ +/* $Id: chc_play.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <time.h> +#include <unistd.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern userinfo_t *currutmp; +extern int usernum; + +typedef int (*play_func_t)(int, board_t, board_t); + +static int chc_ipass = 0, chc_hepass = 0; +int chc_lefttime; +int chc_my, chc_turn, chc_selected, chc_firststep; +char chc_warnmsg[64], *chc_mateid; +rc_t chc_from, chc_to, chc_select, chc_cursor; +int chc_hiswin, chc_hislose, chc_histie; + +#define CHC_TIMEOUT 300 +#define SIDE_ROW 10 +#define TURN_ROW 11 +#define STEP_ROW 12 +#define TIME_ROW 13 +#define WARN_ROW 15 +#define MYWIN_ROW 17 +#define HISWIN_ROW 18 + +static int hisplay(int s, board_t board, board_t tmpbrd) { + int start_time; + int endgame = 0, endturn = 0; + + start_time = time(NULL); + while(!endturn) { + chc_lefttime = CHC_TIMEOUT - (time(NULL) - start_time); + if(chc_lefttime < 0) { + chc_lefttime = 0; + + /* to make him break out igetkey() */ + chc_from.r = -2; + chc_sendmove(s); + } + chc_drawline(board, TIME_ROW); + move(1, 0); + oflush(); + switch(igetkey()) { + case 'q': + endgame = 2; + endturn = 1; + break; + case 'p': + if(chc_hepass) { + chc_from.r = -1; + chc_sendmove(s); + endgame = 3; + endturn = 1; + } + break; + case I_OTHERDATA: + if(chc_recvmove(s)) { /* disconnect */ + endturn = 1; + endgame = 1; + } else { + if(chc_from.r == -1) { + chc_hepass = 1; + strcpy(chc_warnmsg, "\033[1;33m�n�D�M��!\033[m"); + chc_drawline(board, WARN_ROW); + } else { + chc_from.r = 9 - chc_from.r, chc_from.c = 8 - chc_from.c; + chc_to.r = 9 - chc_to.r, chc_to.c = 8 - chc_to.c; + chc_cursor = chc_to; + if(CHE_P(board[chc_to.r][chc_to.c]) == 1) + endgame = 2; + endturn = 1; + chc_hepass = 0; + chc_drawline(board, STEP_ROW); + chc_movechess(board); + chc_drawline(board, LTR(chc_from.r)); + chc_drawline(board, LTR(chc_to.r)); + } + } + break; + } + } + return endgame; +} + +static int myplay(int s, board_t board, board_t tmpbrd) { + int ch, start_time; + int endgame = 0, endturn = 0; + + chc_ipass = 0, chc_selected = 0; + start_time = time(NULL); + chc_lefttime = CHC_TIMEOUT - (time(NULL) - start_time); + bell(); + while(!endturn) { + chc_drawline(board, TIME_ROW); + chc_movecur(chc_cursor.r, chc_cursor.c); + oflush(); + ch = igetkey(); + chc_lefttime = CHC_TIMEOUT - (time(NULL) - start_time); + if(chc_lefttime < 0) + ch = 'q'; + switch(ch) { + case I_OTHERDATA: + if(chc_recvmove(s)) { /* disconnect */ + endgame = 1; + endturn = 1; + } else if(chc_from.r == -1 && chc_ipass) { + endgame = 3; + endturn = 1; + } + break; + case KEY_UP: + chc_cursor.r--; + if(chc_cursor.r < 0) + chc_cursor.r = BRD_ROW - 1; + break; + case KEY_DOWN: + chc_cursor.r++; + if(chc_cursor.r >= BRD_ROW) + chc_cursor.r = 0; + break; + case KEY_LEFT: + chc_cursor.c--; + if(chc_cursor.c < 0) + chc_cursor.c = BRD_COL - 1; + break; + case KEY_RIGHT: + chc_cursor.c++; + if(chc_cursor.c >= BRD_COL) + chc_cursor.c = 0; + break; + case 'q': + endgame = 2; + endturn = 1; + break; + case 'p': + chc_ipass = 1; + chc_from.r = -1; + chc_sendmove(s); + strcpy(chc_warnmsg, "\033[1;33m�n�D�M��!\033[m"); + chc_drawline(board, WARN_ROW); + bell(); + break; + case '\r': + case '\n': + case ' ': + if(chc_selected) { + if(chc_cursor.r == chc_select.r && + chc_cursor.c == chc_select.c) { + chc_selected = 0; + chc_drawline(board, LTR(chc_cursor.r)); + } else if(chc_canmove(board, chc_select, chc_cursor)) { + if(CHE_P(board[chc_cursor.r][chc_cursor.c]) == 1) + endgame = 1; + chc_from = chc_select; + chc_to = chc_cursor; + if(!endgame) { + memcpy(tmpbrd, board, sizeof(board_t)); + chc_movechess(tmpbrd); + } + if(endgame || !chc_iskfk(tmpbrd)) { + chc_drawline(board, STEP_ROW); + chc_movechess(board); + chc_sendmove(s); + chc_selected = 0; + chc_drawline(board, LTR(chc_from.r)); + chc_drawline(board, LTR(chc_to.r)); + endturn = 1; + } else { + strcpy(chc_warnmsg, "\033[1;33m���i�H������\033[m"); + bell(); + chc_drawline(board, WARN_ROW); + } + } + } else if(board[chc_cursor.r][chc_cursor.c] && + CHE_O(board[chc_cursor.r][chc_cursor.c]) == chc_turn) { + chc_selected = 1; + chc_select = chc_cursor; + chc_drawline(board, LTR(chc_cursor.r)); + } + break; + } + } + return endgame; +} + +extern userec_t cuser; + +static void mainloop(int s, board_t board) { + int endgame; + board_t tmpbrd; + play_func_t play_func[2]; + + play_func[chc_my] = myplay; + play_func[chc_my ^ 1] = hisplay; + for(chc_turn = 1, endgame = 0; !endgame; chc_turn ^= 1) { + chc_firststep = 0; + chc_drawline(board, TURN_ROW); + if(chc_ischeck(board, chc_turn)) { + strcpy(chc_warnmsg, "\033[1;31m�N�x!\033[m"); + bell(); + } else + chc_warnmsg[0] = 0; + chc_drawline(board, WARN_ROW); + endgame = play_func[chc_turn](s, board, tmpbrd); + } + + if(endgame == 1) { + strcpy(chc_warnmsg, "���{��F!"); + cuser.chc_win++; + } else if(endgame == 2) { + strcpy(chc_warnmsg, "�A�{��F!"); + cuser.chc_lose++; + } else { + strcpy(chc_warnmsg, "�M��"); + cuser.chc_tie++; + } + cuser.chc_lose--; + passwd_update(usernum, &cuser); + chc_drawline(board, WARN_ROW); + bell(); + oflush(); +} + +extern userec_t xuser; + +static void chc_init(int s, board_t board) { + userinfo_t *my = currutmp; + + setutmpmode(CHC); + clear(); + chc_warnmsg[0] = 0; + chc_my = my->turn; + chc_mateid = my->mateid; + chc_firststep = 1; + chc_init_board(board); + chc_redraw(board); + chc_cursor.r = 9, chc_cursor.c = 0; + add_io(s, 0); + + if(my->turn) chc_recvmove(s); + passwd_query(usernum, &xuser); + cuser.chc_win = xuser.chc_win; + cuser.chc_lose = xuser.chc_lose + 1; + cuser.chc_tie = xuser.chc_tie; + cuser.money = xuser.money; + passwd_update(usernum, &cuser); + + getuser(chc_mateid); + chc_hiswin = xuser.chc_win; + chc_hislose = xuser.chc_lose; + chc_histie = xuser.chc_tie; + + if(!my->turn) { + chc_sendmove(s); + chc_hislose++; + } + + chc_redraw(board); +} + +void chc(int s) { + board_t board; + + chc_init(s, board); + mainloop(s, board); + close(s); + add_io(0, 0); + if(chc_my) pressanykey(); +} diff --git a/mbbsd/chc_rule.c b/mbbsd/chc_rule.c new file mode 100644 index 00000000..35d8fe6a --- /dev/null +++ b/mbbsd/chc_rule.c @@ -0,0 +1,186 @@ +/* $Id: chc_rule.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +extern rc_t chc_from, chc_to; +extern int chc_my; + +#define CENTER(a, b) (((a) + (b)) >> 1) + +void chc_init_board(board_t board) { + memset(board, 0, sizeof(board_t)); + board[0][4] = CHE(1, chc_my ^ 1); /* �N */ + board[0][3] = board[0][5] = CHE(2, chc_my ^ 1); /* �h */ + board[0][2] = board[0][6] = CHE(3, chc_my ^ 1); /* �H */ + board[0][0] = board[0][8] = CHE(4, chc_my ^ 1); /* �� */ + board[0][1] = board[0][7] = CHE(5, chc_my ^ 1); /* �� */ + board[2][1] = board[2][7] = CHE(6, chc_my ^ 1); /* �] */ + board[3][0] = board[3][2] = board[3][4] = + board[3][6] = board[3][8] = CHE(7, chc_my ^ 1); /* �� */ + + board[9][4] = CHE(1, chc_my); /* �� */ + board[9][3] = board[9][5] = CHE(2, chc_my); /* �K */ + board[9][2] = board[9][6] = CHE(3, chc_my); /* �� */ + board[9][0] = board[9][8] = CHE(4, chc_my); /* �� */ + board[9][1] = board[9][7] = CHE(5, chc_my); /* �X */ + board[7][1] = board[7][7] = CHE(6, chc_my); /* �� */ + board[6][0] = board[6][2] = board[6][4] = + board[6][6] = board[6][8] = CHE(7, chc_my); /* �L */ +} + +void chc_movechess(board_t board) { + board[chc_to.r][chc_to.c] = board[chc_from.r][chc_from.c]; + board[chc_from.r][chc_from.c] = 0; +} + +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; +} + +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; +} + +int chc_canmove(board_t board, rc_t from, rc_t to) { + int i; + int rd, cd, turn; + + 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 1: /* �N �� */ + if(!(rd == 1 && cd == 0) && + !(rd == 0 && cd == 1)) + return 0; + if((turn == (chc_my ^ 1) && to.r > 2) || + (turn == chc_my && to.r < 7) || + to.c < 3 || to.c > 5) + return 0; + break; + case 2: /* �h �K */ + if(!(rd == 1 && cd == 1)) + return 0; + if((turn == (chc_my ^ 1) && to.r > 2) || + (turn == chc_my && to.r < 7) || + to.c < 3 || to.c > 5) + return 0; + break; + case 3: /* �H �� */ + if(!(rd == 2 && cd == 2)) + return 0; + if((turn == (chc_my ^ 1) && to.r > 4) || + (turn == chc_my && to.r < 5)) + return 0; + /* ��H�L */ + if(board[CENTER(from.r, to.r)][CENTER(from.c, to.c)]) + return 0; + break; + case 4: /* �� */ + if(!(rd > 0 && cd == 0) && + !(rd == 0 && cd > 0)) + return 0; + if(between(board, from, to, rd == 0)) + return 0; + break; + case 5: /* �� �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 6: /* �] �� */ + 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 7: /* �� �L */ + if(!(rd == 1 && cd == 0) && + !(rd == 0 && cd == 1)) + return 0; + if(((turn == (chc_my ^ 1) && to.r < 5) || + (turn == chc_my && to.r > 4)) && + cd != 0) + return 0; + if((turn == (chc_my ^ 1) && to.r < from.r) || + (turn == chc_my && to.r > from.r)) + return 0; + break; + } + return 1; +} + +static void findking(board_t board, int turn, rc_t *buf) { + int i, r, c; + + r = (turn == (chc_my ^ 1)) ? 0 : 7; + for(i = 0; i < 3; r++, i++) + for(c = 3; c < 6; c++) + if(CHE_P(board[r][c]) == 1 && + CHE_O(board[r][c]) == turn) { + buf->r = r, buf->c = c; + return ; + } +} + +int chc_iskfk(board_t board) { + rc_t from, to; + + findking(board, 0, &to); + findking(board, 1, &from); + if(from.c == to.c && between(board, from, to, 0) == 0) + return 1; + return 0; +} + +int chc_ischeck(board_t board, int turn) { + rc_t from, to; + + findking(board, turn, &to); + 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; +} diff --git a/mbbsd/chicken.c b/mbbsd/chicken.c new file mode 100644 index 00000000..f789925f --- /dev/null +++ b/mbbsd/chicken.c @@ -0,0 +1,989 @@ +/* $Id: chicken.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +#define NUM_KINDS 13 /* ���h�ֺذʪ� */ + +static const char *cage[17] = { + "�ϥ�", "�g��", "���~", "�֦~", "�C�K", "�C�~", + "�C�~", "���O", "���~", "���~", "���~", "���~", + "���~", "�Ѧ~", "�Ѧ~", "������", "�j��"}; +static const char *chicken_type[NUM_KINDS] = { + "�p��", "���֤k", "�i�h", "�j��", + "���s", "���N", "��", "�����p�s", + "����", "�c�]", "�Ԫ�", "����", + "���^�E"}; +static const char *chicken_food[NUM_KINDS] = { + "���}��", "��i�p��", "���ƫK��", "������", + "����", "�p��", "�氮", "�p���氮", + "�_��", "�F��", "����", "�K��", + "���L"}; +static const int egg_price[NUM_KINDS] = { + 5, 25, 30, 40, + 80, 50, 15, 35, + 17, 100, 85, 200, + 200}; +static const int food_price[NUM_KINDS] = { + 4, 6, 8, 10, + 12, 12, 5, 6, + 5, 20, 15, 23, + 23}; +static const char *attack_type[NUM_KINDS] = { + "��", "�@��", "�l", "�r", + "����", "��", "��", "��", + "�r","�U�N","�t��","�ҥ�", + "�C��"}; + +static const char *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 +}; + +extern userec_t cuser; + +static chicken_t *mychicken = &cuser.mychicken; +static int age; + +static const int 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} +}; + +extern userec_t xuser; +extern int usernum; + +int reload_chicken() { + passwd_query(usernum, &xuser); + memcpy(mychicken, &xuser.mychicken, sizeof(chicken_t)); + if(!mychicken->name[0]) + return 0; + else return 1; +} + +#define CHICKENLOG "etc/chicken" + +static int new_chicken() { + char buf[150]; + int price; + time_t now; + + clear(); + move(2,0); + outs("�w���[�{ \033[33m��\033[37;44m Ptt�d������ \033[33;40m��\033[m.. " + "�ث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 (l)���� $200 (m)���^�E $200\n" + "[0]�ۤv $0\n"); + getdata_str(6, 0, "�п�ܧA�n�i���ʪ��G", buf, 3, LCECHO, "0"); + + buf[0] -= 'a'; + if(buf[0]<0 || buf[0]>NUM_KINDS-1) + return 0; + + mychicken->type = buf[0]; + + reload_money(); + price = egg_price[(int)mychicken->type]; + if(cuser.money < price) { + prints("\n �������R�J�J,�J�J�n %d ��", price); + refresh(); + return 0; + } + vice(price,"�d���J"); + while(strlen(mychicken->name)<3) + getdata(8, 0, "���e���Ӧn�W�r�G", mychicken->name, 18, DOECHO); + + now = time(NULL); + sprintf(buf,"\033[31m%s \033[m�i�F�@���s\033[33m %s \033[m�� " + "\033[32m%s\033[m �� %s",cuser.userid, + mychicken->name,chicken_type[(int)mychicken->type],ctime(&now)); + log_file(CHICKENLOG,buf); + 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; + return 1; +} + +int show_file(char *filename, int y, int lines, int mode) { + FILE *fp; + char buf[256]; + + if(y >= 0) + move(y,0); + clrtoline(lines + y); + if((fp=fopen(filename,"r"))) { + while(fgets(buf,256,fp) && lines--) + outs(Ptt_prints(buf,mode)); + fclose(fp); + } else + return 0; + return 1; +} + +static void show_chicken_stat(chicken_t *thechicken) { + struct tm *ptime; + + ptime = localtime(&thechicken->birthday); + prints(" Name :\033[33m%s\033[m (\033[32m%s\033[m)%*s�ͤ� " + ":\033[31m%02d\033[m�~\033[31m%2d\033[m��\033[31m%2d\033[m�� " + "(\033[32m%s %d��\033[m)\n" + " ��:\033[33m%5d/%-5d\033[m �k:\033[33m%5d/%-5d\033[m �����O:" + "\033[33m%-7d\033[m �ӱ� :\033[33m%-7d\033[m ���� :\033[33m%-7d" + "\033[m \n" + " �ּ� :\033[33m%-7d\033[m ���N :\033[33m%-7d\033[m �h�� :" + "\033[33m%-7d\033[m ��� :\033[33m%-7d \033[m�魫 :" + "\033[33m%-5.2f\033[m \n" + " �f�� :\033[33m%-7d\033[m ���b :\033[33m%-7d\033[m ���� :" + "\033[33m%-7d\033[m �j�ɤY:\033[33m%-7d\033[m �ī~ :\033[33m%-7d" + "\033[m \n", + thechicken->name, chicken_type[(int)thechicken->type], + 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" +extern char *BBSName; + +void show_chicken_data(chicken_t *thechicken, chicken_t *pkchicken) { + char buf[1024]; + age = ((time(NULL) - thechicken->cbirth)/ (60*60*24)); + if(age < 0) { + thechicken->birthday = thechicken->cbirth = time(NULL)-10*(60*60*24); + age = 10; + } + /*Ptt:debug*/ + thechicken->type %= NUM_KINDS; + clear(); + showtitle(pkchicken ? "��tt������" : "��tt�i����", BBSName); + move(1,0); + + show_chicken_stat(thechicken); + + sprintf(buf, CHICKEN_PIC "/%c%d", thechicken->type + 'a', + age > 16 ? 16 : age); + show_file(buf, 5, 14, NO_RELOAD); + + move(18,0); + + if(thechicken->sick) + outs("�ͯf�F..."); + if(thechicken->sick > thechicken->hp / 5) + outs("\033[5;31m���...�f��!!\033[m"); + + if(thechicken->clean > 150) + outs("\033[31m�S��Sż��..\033[m"); + else if(thechicken->clean > 80) + outs("���Iż.."); + else if(thechicken->clean < 20) + outs("\033[32m�ܰ��b..\033[m"); + + if(thechicken->weight > thechicken->hp_max*4) + outs("\033[31m�ֹ����F!.\033[m"); + else if(thechicken->weight > thechicken->hp_max*3) + outs("\033[32m���ʹ�..\033[m"); + else if(thechicken->weight < (thechicken->hp_max / 4)) + outs("\033[31m�־j���F!..\033[m"); + else if(thechicken->weight < (thechicken->hp_max / 2)) + outs("�j�F.."); + + if(thechicken->tiredstrong > thechicken->hp * 1.7) + outs("\033[31m�ֱo���g�F...\033[m"); + else if(thechicken->tiredstrong > thechicken->hp) + outs("�֤F.."); + else if(thechicken->tiredstrong < thechicken->hp / 4) + outs("\033[32m��O����...\033[m"); + + if(thechicken->hp < thechicken->hp_max / 4) + outs("\033[31m��O�κ�..�a�a�@��..\033[m"); + if(thechicken->happy > 500) + outs("\033[32m�ܧּ�..\033[m"); + else if(thechicken->happy < 100) + outs("���ּ�.."); + if(thechicken->satis > 500) + outs("\033[32m�ܺ���..\033[m"); + else if(thechicken->satis < 50) + outs("������.."); + + if(pkchicken) { + outs("\n"); + show_chicken_stat(pkchicken); + outs("[���N��] ������� [q] ���] [o] �Y�j�ɤY"); + } +} + +static void ch_eat() { + 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_file(CHICKEN_PIC "/eat", 5, 14, NO_RELOAD); + pressanykey(); + } +} + +static void ch_clean() { + mychicken->clean = 0; + mychicken->tiredstrong += + time_change[(int)mychicken->type][TIREDSTRONG] / 3; + show_file(CHICKEN_PIC "/clean", 5, 14, NO_RELOAD); + pressanykey(); +} + +static void ch_guess() { + 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("�A�n�X[\033[32m1\033[m]\033[33m�ŤM\033[m(\033[32m2\033[m)" + "\033[33m���Y\033[m(\033[32m3\033[m)\033[33m��\033[m:\n"); + me = igetch(); + me -= '1'; + if(me > 2 || me < 0) + me = 0; + win = (int)(3.0 * rand()/(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() { + mychicken->book += time_change[(int)mychicken->type][BOOK]; + mychicken->tiredstrong += time_change[(int)mychicken->type][TIREDSTRONG]; + show_file(CHICKEN_PIC "/read", 5, 14, NO_RELOAD); + pressanykey(); +} + +static void ch_kiss() { + 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_file(CHICKEN_PIC "/kiss", 5, 14, NO_RELOAD); + pressanykey(); +} + +static void ch_hit() { + 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] * + rand()/(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_file(CHICKEN_PIC "/hit", 5, 14, NO_RELOAD); + pressanykey(); +} + +extern int b_lines; /* Screen bottom line number: t_lines-1 */ + +void ch_buyitem(int money, char *picture, int *item) { + int num = 0; + char buf[5]; + + getdata_str(b_lines - 1, 0, "�n�R�h�֥��O:", buf, 4, DOECHO, "1"); + num = atoi(buf); + if(num < 1) + return; + reload_money(); + if(cuser.money > money*num) { + *item += num; + vice(money*num,"�ʶR�d��,��L����"); + show_file(picture, 5, 14, NO_RELOAD); + } else { + move(b_lines-1,0); + clrtoeol(); + outs("�{������ !!!"); + } + pressanykey(); +} + +static void ch_eatoo() { + if(mychicken->oo > 0) { + mychicken->oo--; + mychicken->tiredstrong = 0; + if(mychicken->happy > 5) + mychicken->happy -= 5; + show_file(CHICKEN_PIC "/oo", 5, 14, NO_RELOAD); + pressanykey(); + } +} + +static void ch_eatmedicine() { + 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_file(CHICKEN_PIC "/medicine", 5, 14, NO_RELOAD); + pressanykey(); + } +} + +static void ch_kill() { + char buf[150],ans[4]; + + sprintf(buf, "��i�o%s�n�Q�@ 100 ��, �O�_�n��i?(y/N)", + chicken_type[(int)mychicken->type]); + getdata_str(23, 0, buf, ans, 3, DOECHO, "N"); + if(ans[0] == 'y') { + time_t now = time(NULL); + + vice(100,"��i�d���O"); + more(CHICKEN_PIC "/deadth",YEA); + sprintf(buf, "\033[31m%s \033[m�� \033[33m%s\033[m\033[32m %s " + "\033[m�_�F �� %s", cuser.userid, + mychicken->name, chicken_type[(int)mychicken->type], ctime(&now)); + log_file(CHICKENLOG, buf); + mychicken->name[0]=0; + } +} + +static int ch_sell() { +/* + int money = (mychicken->weight - time_change[(int)mychicken->type][WEIGHT]) + *(food_price[(int)mychicken->type])/4 + + ( + + ((mychicken->clean / time_change[(int)mychicken->type][CLEAN]) + + (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 / time_change[(int)mychicken->type][TIREDSTRONG]) + - (mychicken->sick / time_change[(int)mychicken->type][SICK]) + + (mychicken->hp / time_change[(int)mychicken->type][HP_MAX]) + + (mychicken->mm / time_change[(int)mychicken->type][MM_MAX]) + + 7 - abs(age - 7)) * 3 + ; +*/ + int money = (age * food_price[(int)mychicken->type] * 3 + + (mychicken->hp_max * 10 + mychicken->weight) / + time_change[(int)mychicken->type][HP_MAX]) * 3 / 2 - + mychicken->sick; + char buf[150],ans[4]; + time_t now = time(NULL); + + if(money < 0) + money =0 ; + else if(money > MAX_CHICKEN_MONEY) + money = MAX_CHICKEN_MONEY; //������� + if(mychicken->type == 1 || mychicken->type == 7) { + outs("\n\033[31m ��..�˷R��..�c��H�f�O�|�Ǫk����..\033[m"); + pressanykey(); + return 0; + } + if(age < 5) { + outs("\n �٥����~�����"); + pressanykey(); + return 0; + } + if(age > 30) { + outs("\n\033[31m �o..�ӦѨS�H�n�F\033[m"); + pressanykey(); + return 0; + } + + sprintf(buf, "�o��%d��%s�i�H�� %d ��, �O�_�n��?(y/N)", age, + chicken_type[(int)mychicken->type], money); + getdata_str(23, 0, buf, ans, 3, DOECHO, "N"); + if(ans[0]=='y') { + sprintf(buf, "\033[31m%s\033[m �� \033[33m%s\033[m " + "\033[32m%s\033[m �� \033[36m%d\033[m ��F �� %s", + cuser.userid, mychicken->name, + chicken_type[(int)mychicken->type],money,ctime(&now)); + log_file(CHICKENLOG, buf); + mychicken->lastvisit = mychicken->name[0]=0; + passwd_update(usernum, &cuser); + more(CHICKEN_PIC "/sell",YEA); + demoney(money); + return 1; + } + return 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; + } +} + +/* �̮ɶ��ܰʪ���� */ +void time_diff(chicken_t *thechicken) { + int diff; + int theage = ((time(NULL) - thechicken->cbirth)/ (60 * 60 * 24)); + + thechicken->type %= NUM_KINDS ; + diff = (time(NULL)-thechicken->lastvisit)/60; + + if((diff) < 1) + return; + + if(theage > 13 ) /* �Ѧ� */ + geting_old(&thechicken->hp_max, &thechicken->weight, diff, age); + + thechicken->lastvisit = time(NULL); + 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(mychicken->clean > 1000) + mychicken->sick += (mychicken->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() { + /* ż�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(chicken_t *thechicken) { + int i; + char buf[150]; + time_t now = time(NULL); + + 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) { + sprintf(buf,"\033[31m%s\033[m �үk�R��\033[33m %s\033[32m %s " + "\033[m���F �� %s", + cuser.userid, thechicken->name, + chicken_type[(int)thechicken->type], + ctime(&now)); + log_file(CHICKENLOG, buf); + mychicken->name[0] = 0; + passwd_update(usernum, &cuser); + } + 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; +} + +int isdeadth(chicken_t *thechicken) { + int i; + + if(!(i = deadtype(thechicken))) + return 0; + return showdeadth(i); +} + +static void ch_changename() { + char buf[150], newname[20] = ""; + time_t now = time(NULL); + + getdata_str(b_lines - 1, 0, "��..��Ӧn�W�r�a:", newname, 18, DOECHO, + mychicken->name); + + if(strlen(newname) >= 3 && strcmp(newname,mychicken->name)) { + sprintf(buf, "\033[31m%s\033[m ��k�R��\033[33m %s\033[32m %s " + "\033[m��W��\033[33m %s\033[m �� %s", + cuser.userid, mychicken->name, + chicken_type[(int)mychicken->type], + newname, ctime(&now)); + strcpy(mychicken->name, newname); + log_file(CHICKENLOG,buf); + } +} + +static int select_menu() { + char ch; + + reload_money(); + move(19,0); + prints("\033[44;37m �� :\033[33m %-10d " + " \033[m\n" + "\033[33m(\033[37m1\033[33m)�M�z (\033[37m2\033[33m)�Y�� " + "(\033[37m3\033[33m)�q�� (\033[37m4\033[33m)��� " + "(\033[37m5\033[33m)�˥L (\033[37m6\033[33m)���L " + "(\033[37m7\033[33m)�R%s$%d (\033[37m8\033[33m)�Y�ɤY\n" + "(\033[37m9\033[33m)�Y�f�� (\033[37mo\033[33m)�R�j�ɤY$100 " + "(\033[37mm\033[33m)�R��$10 (\033[37mk\033[33m)��i " + "(\033[37ms\033[33m)�汼 (\033[37mn\033[33m)��W " + "(\033[37mq\033[33m)���}:\033[m", + 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(); + check_sick(); + break; + case '2': + ch_eat(); + check_sick(); + break; + case '3': + ch_guess(); + check_sick(); + break; + case '4': + ch_book(); + check_sick(); + break; + case '5': + ch_kiss(); + break; + case '6': + ch_hit(); + check_sick(); + break; + case '7': + ch_buyitem(food_price[(int)mychicken->type], CHICKEN_PIC "/food", + &mychicken->food); + break; + case '8': + ch_eatoo(); + break; + case '9': + ch_eatmedicine(); + break; + case 'O': + case 'o': + ch_buyitem(100, CHICKEN_PIC "/buyoo", &mychicken->oo); + break; + case 'M': + case 'm': + ch_buyitem(10, CHICKEN_PIC "/buymedicine", &mychicken->medicine); + break; + case 'N': + case 'n': + ch_changename(); + break; + case 'K': + case 'k': + ch_kill(); + return 0; + case 'S': + case 's': + if(!ch_sell()) break; + 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], + money = price + (rand() % price); + + if(time(NULL) - thechicken->lastvisit > (60 * 60 * 24 * 7)) + return 0; + outmsg("\033[33;44m���F�ɦu��\033[37;45m �O�`�� �ڬO�����A�� \033[m"); + bell(); + igetch(); + outmsg("\033[33;44m���F�ɦu��\033[37;45m �A�L�k���ڤ��y �]���ڬO�t�F, " + "�̪�ʿ��Q�ȥ~�� \033[m"); + bell(); + igetch(); + sprintf(buf, "\033[33;44m���F�ɦu��\033[37;45m " + "�A���@�ӭ訫���[��%s�n�۴��^�Ӷ�? �u�n%d���� \033[m", + chicken_type[(int)thechicken->type], price*2); + 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*2) { + outmsg("\033[33;44m���F�ɦu��\033[37;45m ���� ���S�a�� " + "�S�����p�� �֥h�w���a \033[m"); + bell(); + igetch(); + return 0; + } + strcpy(thechicken->name, "[�ߦ^�Ӫ�]"); + thechicken->hp = thechicken->hp_max; + thechicken->sick = 0; + thechicken->satis = 2; + vice(money,"�F�ɦu��"); + sprintf(buf, "\033[33;44m���F�ɦu��\033[37;45m OK�F �O�o���L�I�F�� " + "���M�i�ॢ�� ���b�ڤ]����Ptt ���A%d�N�n \033[m", money); + outmsg(buf); + bell(); + igetch(); + return 1; + } + outmsg("\033[33;44m���F�ɦu��\033[37;45m ���M���ڧ|�H! �o�~�Y�R�u���ȿ� " + "���D�ڦA�ӧ�A �A�A�]�S���|�F \033[m"); + bell(); + igetch(); + thechicken->lastvisit = 0; + passwd_update(usernum, &cuser); + return 0; +} + +#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 + +int chicken_main() { + lockreturn0(CHICKEN, LOCK_MULTI); + + reload_chicken(); + age = ((time(NULL) - mychicken->cbirth)/ (60*60*24)); + if(!mychicken->name[0] && !recover_chicken(mychicken) && !new_chicken()) { + unlockutmpmode(); + return 0; + } + + do { + time_diff(mychicken); + if(isdeadth(mychicken)) + break; + show_chicken_data(mychicken, NULL); + } while(select_menu()); + reload_money(); + passwd_update(usernum, &cuser); + unlockutmpmode(); + return 0; +} + +extern userinfo_t *currutmp; +extern struct utmpfile_t *utmpshm; + +int chickenpk(int fd) { + char mateid[IDLEN + 1], data[200], buf[200]; + int ch = 0; + + userinfo_t *uin = &utmpshm->uinfo[currutmp->destuip]; + userec_t ouser; + chicken_t *ochicken = &ouser.mychicken; + int r, attmax, i, datac, duid = currutmp->destuid, catched=0, count=0; + + lockreturn0(CHICKEN, LOCK_MULTI); + + strcpy(mateid, currutmp->mateid); /*���⪺id��local buffer�O��*/ + + getuser(mateid) ; + memcpy(&ouser, &xuser, sizeof(userec_t)); + reload_chicken(); + if(!ochicken->name[0] || !mychicken->name[0]) { + outmsg("���@��S���d��"); /* Ptt:����page�ɧ��d���汼 */ + bell(); + refresh(); + add_io(0, 0); + close(fd); + unlockutmpmode(); + sleep(1); + return 0; + } + + show_chicken_data(ochicken, mychicken); + add_io(fd, 3); /* ��fd�[��igetch�ʵ� */ + while(1) { + r = rand(); + ch = igetkey(); + getuser(mateid) ; + memcpy(&ouser, &xuser, sizeof(userec_t)); + reload_chicken(); + 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) { + sprintf(data, "l�� %s ���]�F\n", + ochicken->name); + } + break; + case 'n': + catched =0; + default: + case 'k': + r = r % (attmax + 2); + if(r) { + sprintf(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 + sprintf(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; + sprintf(data, "M%s �Y�F���j�ɤY�ɥR��O\n", + mychicken->name); + } else + sprintf(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)) + sprintf(data, "q%s ���]�F\n", + mychicken->name); + else + sprintf(data, "c%s �Q���], ���Q %s ���F\n", + mychicken->name, ochicken->name); + break; + } + if(deadtype(ochicken)) { + strtok(data,"\n"); + strcpy(buf, data); + sprintf(data, "d%s , %s �Q %s �����F\n", + buf + 1, ochicken->name, mychicken->name); + } + move(17,0); + outs(data+1); + i = strlen(data) +1; + passwd_update(duid, &ouser); + passwd_update(usernum, &cuser); + send(fd, data, i, 0); + if(data[0]=='q' || data[0]=='d') + break; + } else { + move(17, 0); + if(count++ > 30) + break; + } + } + add_io(0, 0); /* ��igetch���@�^ */ + pressanykey(); + close(fd); + if(!showdeadth(deadtype(mychicken))); + unlockutmpmode(); + return 0; +} diff --git a/mbbsd/dark.c b/mbbsd/dark.c new file mode 100644 index 00000000..52741617 --- /dev/null +++ b/mbbsd/dark.c @@ -0,0 +1,456 @@ +/* $Id: dark.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.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; + +static item brd[4][8]; +static cur curr; /* 6 �� bytes */ +extern userinfo_t *currutmp; + +static char *rname[]={"�L","��","�X","��","��","�K","��"}; +static char *bname[]={"��","�]","��","��","�H","�h","�N"}; + +static sint cury[]={3,5,7,9}, curx[]={5,9,13,17,21,25,29,33}; +static sint rcount,bcount,cont,fix; /* cont:�O�_�i�s�Y */ +static sint my=0,mx=0,mly=-1,mlx=-1; /* ���ʪ��y�� �� ��l���y�� */ + +static sint cur_eaty,cur_eatx; /* �Y������l���q�X�y�� */ +static void brdswap(sint y,sint x,sint ly,sint lx) { + memcpy(&brd[y][x],&brd[ly][lx],sizeof(item)); + brd[ly][lx].die=1; + brd[ly][lx].color=-1; /* �S�o��color */ + brd[ly][lx].value=-1; +} + +static void pprints(sint y,sint x,char* s) { + move(y,x); + clrtoeol(); + prints("%s",s); +} + +static sint Is_win(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 && brd[y][x].die==0)|| + (abs(lx-x)==1 && 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(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(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)) && 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(sint y,sint x, sint ly, sint lx) { + if(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() { + 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(brd, sizeof(brd)); + bzero(tem, sizeof(tem)); + bzero(&curr, sizeof(curr)); + srand(getpid()%2731+time(NULL)%3219); + for(y=0;y<4;y++) + for(x=0;x<8;x++) + while(1) { + index=rand()%32; + if(tem[index]) continue; + brd[y][x].color=(index>15)?0:1; + brd[y][x].value=value[index]; + tem[index]=1; + break; + } +} + +static void brd_prints() { + clear(); + move(1,0); + outs(" + [43;30m�~�w�s�w�s�w�s�w�s�w�s�w�s�w�s�w��[m + [43;30m�x���x���x���x���x���x���x���x���x[m + [43;30m�u�w�q�w�q�w�q�w�q�w�q�w�q�w�q�w�t[m + [43;30m�x���x���x���x���x���x���x���x���x[m + [43;30m�u�w�q�w�q�w�q�w�q�w�q�w�q�w�q�w�t[m + [43;30m�x���x���x���x���x���x���x���x���x[m + [43;30m�u�w�q�w�q�w�q�w�q�w�q�w�q�w�q�w�t[m + [43;30m�x���x���x���x���x���x���x���x���x[m + [43;30m���w�r�w�r�w�r�w�r�w�r�w�r�w�r�w��[m + "); +} + +static void draw_line(sint y, sint f) { + sint i; + char buf[1024],tmp[256]; + + *buf = 0; + *tmp = 0; + strcpy(buf,"\033[43;30m"); + for(i=0; i<8; i++) + { + if(brd[y][i].die==1) + sprintf(tmp,"�x "); + else if(brd[y][i].out==0) + sprintf(tmp,"�x��"); + else { + sprintf(tmp, "�x\033[%s1;%dm%s\033[m\033[43;30m", + (f==i)?"1;47;":"",(brd[y][i].color)?31:34, + (brd[y][i].color)?rname[brd[y][i].value]: + bname[brd[y][i].value]); + } + strcat(buf,tmp); + } + strcat(buf,"�x\033[m"); + + move(cury[y],3); + clrtoeol(); + prints("%s",buf); +} + +static void redraw() { + sint i=0; + for(;i<4;i++) + draw_line(i,-1); +} + +static sint playing(sint fd, sint color,sint ch,sint *b, userinfo_t *uin) { + curr.end = 0; + move(cury[my],curx[mx]); + + if(fix) { + if(ch=='s') { + fix=0; *b=0; return 0; + } else { + draw_line(mly,-1); + } + } + + switch(ch) { + case KEY_LEFT: + if(mx == 0) mx=7; + else mx--; + move(cury[my],curx[mx]); + *b=-1; + break; + case KEY_RIGHT: + if(mx==7) mx=0; + else mx++; + move(cury[my],curx[mx]); + *b=-1; + break; + case KEY_UP: + if(my==0) my=3; + else my--; + move(cury[my],curx[mx]); + *b=-1; + break; + case KEY_DOWN: + if(my==3) my=0; + else my++; + move(cury[my],curx[mx]); + *b=-1; + break; + case 'q':case 'Q': + if(!color) bcount=0; + else 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(brd[my][mx].out==1) + { + if(brd[my][mx].color != color) + { + *b=-1; + break; + } + if(mly<0) /*�i�H���*/ + { + mly=my;mlx=mx; + draw_line(my,mx); + *b=-1; + break; + } + else if(mly == my && mlx == mx) /*����F*/ + { + mly=-1;mlx=-1; + draw_line(my,-1); + }else + { + draw_line(mly,-1); + mly=my;mlx=mx; + if(brd[mly][mlx].value == 1) fix=1; + draw_line(my,mx); + } + *b=-1; + break; + } + /* ½�}�Ѥl */ + if(mly >=0 ){ *b=-1; break;} /*���ӴN�O½�}��*/ + /* �M�w�@�}�l���C�� */ + if(currutmp->color=='.'){ + if(uin->color!='1' && uin->color!='0') + currutmp->color=(brd[my][mx].color)?'1':'0'; + else + currutmp->color=(uin->color=='0')?'1':'0';} + brd[my][mx].out=1; + draw_line(my,-1); + move(cury[my],curx[mx]); + *b=0; + break; + case 'u': + move(0,0);clrtoeol(); + prints("%s��%s cont=%d",(brd[my][mx].color == RED)?"��":"��",rname[brd[my][mx].value],cont); + *b=-1; + break; + case '\r': /* �Y or ���� ly��lx�����j��0*/ + case '\n': + if( + mly >= 0 /* �n����l */ + && + brd[mly][mlx].color != brd[my][mx].color /* �P�⤣�ಾ�ʤ]����Y */ + && + (Is_move(my,mx,mly,mlx) || Is_win(brd[mly][mlx],brd[my][mx],my,mx,mly,mlx)) + ) + { + if(fix && brd[my][mx].value<0) + { + *b=-1;return 0; + } + if(brd[my][mx].value>=0&&brd[my][mx].die==0) + { + if(!color) bcount--; + else rcount--; + move(cur_eaty,cur_eatx); + prints("%s",(color)?bname[brd[my][mx].value]:rname[brd[my][mx].value]); + if(cur_eatx>=26) + { cur_eatx=5;cur_eaty++; } + else + cur_eatx+=3; + } + brdswap(my,mx,mly,mlx); + draw_line(mly,-1); + draw_line( my,-1); + if(fix==1) *b=-1; + else { mly=-1;mlx=-1;*b=0; } + } + else *b=-1; + break; + default: + *b=-1; + } + + if(!rcount) + return -1; + else if(!bcount) + return -1; + if(*b == -1) return 0; + curr.y = my;curr.x = mx; curr.end=(!*b)?1:0; + send(fd,&curr,sizeof(curr),0); + send(fd,&brd,sizeof(brd),0); + return 0; +} + +int main_dark(int fd,userinfo_t *uin) { + sint end=0,ch=1,go_on,i=0,cont=0; + char buf[16]; + *buf=0;fix=0; + currutmp->color='.'; // '.' �����٨S�M�w�C�� + rcount=16;bcount=16; // initialize + cur_eaty=18,cur_eatx=5; + brd_prints(); + if(currutmp->turn) + { + brd_rand(); + send(fd,&brd,sizeof(brd),0); + pprints(21,0," [1;37m[1;33m��[1;37m�A�O����[m"); + pprints(22,0," [1;33m��[5;35m����A�U�F[m"); + }else + { + recv(fd,&brd,sizeof(brd),0); + pprints(21,0," [1;33m��[1;37m�A�O���[m"); + } + move(12,3); + prints("%s[0��0��][5;31m����[1;37m.[m%s[0��0��]",currutmp->userid,currutmp->mateid); + outs(" + [1;36m����[1;31m�\\���[1;36m������������[m + [1;36m��[1;33m ��������[1;37m: [1;35m����[m + [1;36m��[1;33m ��[1;37m: [1;35m ��l,½�l[m + [1;36m��[1;33m enter[1;37m: [1;35m �Y��,���[m +�@[1;33m�w�g�ѨM��[1;37m:[1;36m�@�@ ��[1;33m ��[1;37m: [1;35m �X��[m + �@�@ [1;36m��[1;33m ��[1;37m: [1;35m �{��[m + [1;36m��[1;33m ��[1;37m: [1;35m ����[m"); + + 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 = igetkey(); + if(ch == I_OTHERDATA) + { + ch=recv(fd,&curr,sizeof(curr),0); + if(ch!=sizeof(curr)) + { + if(uin->turn=='e') { end=-3;break; } + else if(uin->turn!='w') { end=-1; currutmp->turn='w'; break; } + end=-1; break; + } + + if(curr.end==-3) pprints(23,30,"\033[33m�n�D�X��\033[m"); + else if(curr.end==-4) pprints(23,30,"\033[33m�n�D����\033[m"); + else if(curr.end==-5) pprints(23,30,"\033[33m�n�D�s�Y\033[m"); + else pprints(23,30,""); + + recv(fd,&brd,sizeof(brd),0); + my=curr.y;mx=curr.x; + redraw(); + if(curr.end) + pprints(22,0," [1;33m��[5;35m����A�U�F[m"); + move(cury[my],curx[mx]); + }else + { + if(currutmp->turn=='p') + { + if(ch=='y') { end=-3; currutmp->turn='e'; break; } + else { pprints(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'; + pprints(21,0,(currutmp->color=='1')?" \033[1;33m��[1;31m�A�������\033[m":" \033[1;33m��[1;36m�A���¦��\033[m"); + } + else { pprints(23,30,""); currutmp->turn=(uin->turn)?0:1; } + }else if(currutmp->turn=='g') + { + if(ch=='y') { + cont=1; + pprints(21,0," \033[1;33m��[1;31m�A�������\033[m �i�s�Y"); + } + else { pprints(23,30,""); currutmp->turn=(uin->turn)?0:1; } + } + + if(currutmp->turn==1) + { + if(uin->turn=='g') { cont=1;uin->turn=(currutmp->turn)?0:1; pprints(21,10,"�i�s�Y"); } + end=playing(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';curr.end=-3; + send(fd,&curr,sizeof(curr),0); + send(fd,&brd,sizeof(buf),0); + continue; + } + else if(end == -4) { + if(currutmp->color!='1'&&currutmp->color!='0') + continue; + uin->turn='c';i=0;curr.end=-4; + send(fd,&curr,sizeof(curr),0); + send(fd,&brd,sizeof(buf),0); + continue; + } + else if(end == -5) { + uin->turn='g';curr.end=-5; + send(fd,&curr,sizeof(curr),0); + send(fd,&brd,sizeof(buf),0); + continue; + } + if(!i && currutmp->color=='1') + { pprints(21,0," \033[1;33m��[1;31m�A�������\033[m");i++;move(cury[my],curx[mx]); } + if(!i && currutmp->color=='0') + { pprints(21,0," \033[1;33m��[1;36m�A���¦��\033[m");i++;move(cury[my],curx[mx]); } + + if(uin->turn == 'e') { end=-3; break; } + if(go_on < 0) continue; + + move(22,0);clrtoeol(); + prints(" [1;33m��[1;37m����%s�U �O�ȧO�� �L��ԣ��[m",currutmp->mateid); + currutmp->turn = 0; + uin->turn = 1; + }else + { + if(ch == 'q'){uin->turn='w';break;} + move(22,0);clrtoeol(); + prints(" [1;33m��[1;37m����%s�U �O�ȧO�� �L��ԣ��[m",currutmp->mateid); + } + } + } + + switch(end) + { + case -1: + case -2: + if(currutmp->turn=='w'){ move(22,0);clrtoeol();prints("[1;31m�AĹ�F.. �u�O����~~[m");} + else {move(22,0);clrtoeol();prints("[1;31m�鱼�F��.....�U�����L�n��!![m");} + break; + case -3: + pprints(22,0,"[1;31m�X�ѭ�!! �U���b�����U�a ^_^[m"); + break; + default: + add_io(0,0); + close(fd); + pressanykey(); + return 0; + } + add_io(0,0); + close(fd); + pressanykey(); + return 0; +} diff --git a/mbbsd/descrypt.c b/mbbsd/descrypt.c new file mode 100644 index 00000000..3bb0a5e5 --- /dev/null +++ b/mbbsd/descrypt.c @@ -0,0 +1,616 @@ +/* $Id: descrypt.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ + +/* + * FreeSec: libcrypt for NetBSD + * + * Copyright (c) 1994 David Burren + * All rights reserved. + * + * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet + * crypt.c should now *only* export crypt(), in order to make + * binaries of libcrypt exportable from the USA + * + * 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 author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD: src/secure/lib/libcrypt/crypt.c,v 1.11 1999/08/28 01:30:24 peter Exp $ + * + * This is an original implementation of the DES and the crypt(3) interfaces + * by David Burren <davidb@werj.com.au>. + * + * An excellent reference on the underlying algorithm (and related + * algorithms) is: + * + * B. Schneier, Applied Cryptography: protocols, algorithms, + * and source code in C, John Wiley & Sons, 1994. + * + * Note that in that book's description of DES the lookups for the initial, + * pbox, and final permutations are inverted (this has been brought to the + * attention of the author). A list of errata for this book has been + * posted to the sci.crypt newsgroup by the author and is available for FTP. + * + * ARCHITECTURE ASSUMPTIONS: + * This code assumes that u_longs are 32 bits. It will probably not + * operate on 64-bit machines without modifications. + * It is assumed that the 8-byte arrays passed by reference can be + * addressed as arrays of u_longs (ie. the CPU is not picky about + * alignment). + */ + +#ifndef HAVE_DES_CRYPT + +#include <sys/types.h> +#include <sys/param.h> +#include <pwd.h> +#include <string.h> + +static unsigned char IP[64] = { + 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 +}; + +static unsigned char inv_key_perm[64]; +static unsigned char u_key_perm[56]; +static unsigned char key_perm[56] = { + 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 +}; + +static unsigned char key_shifts[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + +static unsigned char inv_comp_perm[56]; +static unsigned char comp_perm[48] = { + 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 +}; + +/* + * No E box is used, as it's replaced by some ANDs, shifts, and ORs. + */ + +static unsigned char u_sbox[8][64]; +static unsigned char sbox[8][64] = { + { + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 + }, + { + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 + }, + { + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 + }, + { + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 + }, + { + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 + }, + { + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 + }, + { + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 + }, + { + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 + } +}; + +static unsigned char un_pbox[32]; +static unsigned char pbox[32] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 +}; + +static unsigned long bits32[32] = { + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + +static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + +static unsigned long saltbits; +static long old_salt; +static unsigned long *bits28, *bits24; +static unsigned char init_perm[64], final_perm[64]; +static unsigned long en_keysl[16], en_keysr[16]; +static unsigned long de_keysl[16], de_keysr[16]; +static int des_initialised = 0; +static unsigned char m_sbox[4][4096]; +static unsigned long psbox[4][256]; +static unsigned long ip_maskl[8][256], ip_maskr[8][256]; +static unsigned long fp_maskl[8][256], fp_maskr[8][256]; +static unsigned long key_perm_maskl[8][128], key_perm_maskr[8][128]; +static unsigned long comp_maskl[8][128], comp_maskr[8][128]; +static unsigned long old_rawkey0, old_rawkey1; + +static unsigned char ascii64[] = +"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +/* 0000000000111111111122222222223333333333444444444455555555556666 */ +/* 0123456789012345678901234567890123456789012345678901234567890123 */ + +static int ascii_to_bin(char ch) { + if(ch > 'z') + return 0; + if(ch >= 'a') + return ch - 'a' + 38; + if(ch > 'Z') + return 0; + if(ch >= 'A') + return ch - 'A' + 12; + if(ch > '9') + return 0; + if(ch >= '.') + return ch - '.'; + return 0; +} + +static void des_init() { + int i, j, b, k, inbit, obit; + unsigned long *p, *il, *ir, *fl, *fr; + + old_rawkey0 = old_rawkey1 = 0L; + saltbits = 0L; + old_salt = 0L; + bits24 = (bits28 = bits32 + 4) + 4; + + /* + * Invert the S-boxes, reordering the input bits. + */ + for(i = 0; i < 8; i++) + for(j = 0; j < 64; j++) { + b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); + u_sbox[i][j] = sbox[i][b]; + } + + /* + * Convert the inverted S-boxes into 4 arrays of 8 bits. + * Each will handle 12 bits of the S-box input. + */ + for(b = 0; b < 4; b++) + for(i = 0; i < 64; i++) + for(j = 0; j < 64; j++) + m_sbox[b][(i << 6) | j] = + (u_sbox[(b << 1)][i] << 4) | + u_sbox[(b << 1) + 1][j]; + + /* + * Set up the initial & final permutations into a useful form, and + * initialise the inverted key permutation. + */ + for(i = 0; i < 64; i++) { + init_perm[final_perm[i] = IP[i] - 1] = i; + inv_key_perm[i] = 255; + } + + /* + * Invert the key permutation and initialise the inverted key + * compression permutation. + */ + for(i = 0; i < 56; i++) { + u_key_perm[i] = key_perm[i] - 1; + inv_key_perm[key_perm[i] - 1] = i; + inv_comp_perm[i] = 255; + } + + /* + * Invert the key compression permutation. + */ + for(i = 0; i < 48; i++) { + inv_comp_perm[comp_perm[i] - 1] = i; + } + + /* + * Set up the OR-mask arrays for the initial and final permutations, + * and for the key initial and compression permutations. + */ + for(k = 0; k < 8; k++) { + for(i = 0; i < 256; i++) { + *(il = &ip_maskl[k][i]) = 0L; + *(ir = &ip_maskr[k][i]) = 0L; + *(fl = &fp_maskl[k][i]) = 0L; + *(fr = &fp_maskr[k][i]) = 0L; + for(j = 0; j < 8; j++) { + inbit = 8 * k + j; + if(i & bits8[j]) { + if((obit = init_perm[inbit]) < 32) + *il |= bits32[obit]; + else + *ir |= bits32[obit-32]; + if ((obit = final_perm[inbit]) < 32) + *fl |= bits32[obit]; + else + *fr |= bits32[obit - 32]; + } + } + } + for(i = 0; i < 128; i++) { + *(il = &key_perm_maskl[k][i]) = 0L; + *(ir = &key_perm_maskr[k][i]) = 0L; + for(j = 0; j < 7; j++) { + inbit = 8 * k + j; + if(i & bits8[j + 1]) { + if((obit = inv_key_perm[inbit]) == 255) + continue; + if(obit < 28) + *il |= bits28[obit]; + else + *ir |= bits28[obit - 28]; + } + } + *(il = &comp_maskl[k][i]) = 0L; + *(ir = &comp_maskr[k][i]) = 0L; + for(j = 0; j < 7; j++) { + inbit = 7 * k + j; + if(i & bits8[j + 1]) { + if((obit=inv_comp_perm[inbit]) == 255) + continue; + if(obit < 24) + *il |= bits24[obit]; + else + *ir |= bits24[obit - 24]; + } + } + } + } + + /* + * Invert the P-box permutation, and convert into OR-masks for + * handling the output of the S-box arrays setup above. + */ + for(i = 0; i < 32; i++) + un_pbox[pbox[i] - 1] = i; + + for(b = 0; b < 4; b++) + for(i = 0; i < 256; i++) { + *(p = &psbox[b][i]) = 0L; + for (j = 0; j < 8; j++) { + if (i & bits8[j]) + *p |= bits32[un_pbox[8 * b + j]]; + } + } + + des_initialised = 1; +} + +static void setup_salt(long salt) { + unsigned long obit, saltbit; + int i; + + if (salt == old_salt) + return; + old_salt = salt; + + saltbits = 0L; + saltbit = 1; + obit = 0x800000; + for (i = 0; i < 24; i++) { + if (salt & saltbit) + saltbits |= obit; + saltbit <<= 1; + obit >>= 1; + } +} + +static int des_setkey(const char *key) { + unsigned long k0, k1, rawkey0, rawkey1; + int shifts, round; + + if(!des_initialised) + des_init(); + + rawkey0 = ntohl(*(unsigned long *) key); + rawkey1 = ntohl(*(unsigned long *) (key + 4)); + + if((rawkey0 | rawkey1) + && rawkey0 == old_rawkey0 + && rawkey1 == old_rawkey1) { + /* + * Already setup for this key. + * This optimisation fails on a zero key (which is weak and + * has bad parity anyway) in order to simplify the starting + * conditions. + */ + return 0; + } + old_rawkey0 = rawkey0; + old_rawkey1 = rawkey1; + + /* + * Do key permutation and split into two 28-bit subkeys. + */ + k0 = key_perm_maskl[0][rawkey0 >> 25] + | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskl[4][rawkey1 >> 25] + | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f]; + k1 = key_perm_maskr[0][rawkey0 >> 25] + | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskr[4][rawkey1 >> 25] + | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f]; + /* + * Rotate subkeys and do compression permutation. + */ + shifts = 0; + for(round = 0; round < 16; round++) { + unsigned long t0, t1; + + shifts += key_shifts[round]; + + t0 = (k0 << shifts) | (k0 >> (28 - shifts)); + t1 = (k1 << shifts) | (k1 >> (28 - shifts)); + + de_keysl[15 - round] = + en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f] + | comp_maskl[1][(t0 >> 14) & 0x7f] + | comp_maskl[2][(t0 >> 7) & 0x7f] + | comp_maskl[3][t0 & 0x7f] + | comp_maskl[4][(t1 >> 21) & 0x7f] + | comp_maskl[5][(t1 >> 14) & 0x7f] + | comp_maskl[6][(t1 >> 7) & 0x7f] + | comp_maskl[7][t1 & 0x7f]; + + de_keysr[15 - round] = en_keysr[round] = + comp_maskr[0][(t0 >> 21) & 0x7f] + | comp_maskr[1][(t0 >> 14) & 0x7f] + | comp_maskr[2][(t0 >> 7) & 0x7f] + | comp_maskr[3][t0 & 0x7f] + | comp_maskr[4][(t1 >> 21) & 0x7f] + | comp_maskr[5][(t1 >> 14) & 0x7f] + | comp_maskr[6][(t1 >> 7) & 0x7f] + | comp_maskr[7][t1 & 0x7f]; + } + return 0; +} + +static int do_des(unsigned long l_in, unsigned long r_in, unsigned long *l_out, + unsigned long *r_out, int count) { + /* + * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format. + */ + unsigned long l, r, *kl, *kr, *kl1, *kr1; + unsigned long f, r48l, r48r; + int round; + + if(count == 0) { + return 1; + } else if(count > 0) { + /* + * Encrypting + */ + kl1 = en_keysl; + kr1 = en_keysr; + } else { + /* + * Decrypting + */ + count = -count; + kl1 = de_keysl; + kr1 = de_keysr; + } + + /* + * Do initial permutation (IP). + */ + l = ip_maskl[0][l_in >> 24] + | ip_maskl[1][(l_in >> 16) & 0xff] + | ip_maskl[2][(l_in >> 8) & 0xff] + | ip_maskl[3][l_in & 0xff] + | ip_maskl[4][r_in >> 24] + | ip_maskl[5][(r_in >> 16) & 0xff] + | ip_maskl[6][(r_in >> 8) & 0xff] + | ip_maskl[7][r_in & 0xff]; + r = ip_maskr[0][l_in >> 24] + | ip_maskr[1][(l_in >> 16) & 0xff] + | ip_maskr[2][(l_in >> 8) & 0xff] + | ip_maskr[3][l_in & 0xff] + | ip_maskr[4][r_in >> 24] + | ip_maskr[5][(r_in >> 16) & 0xff] + | ip_maskr[6][(r_in >> 8) & 0xff] + | ip_maskr[7][r_in & 0xff]; + + while(count--) { + /* + * Do each round. + */ + kl = kl1; + kr = kr1; + round = 16; + while(round--) { + /* + * Expand R to 48 bits (simulate the E-box). + */ + r48l = ((r & 0x00000001) << 23) + | ((r & 0xf8000000) >> 9) + | ((r & 0x1f800000) >> 11) + | ((r & 0x01f80000) >> 13) + | ((r & 0x001f8000) >> 15); + + r48r = ((r & 0x0001f800) << 7) + | ((r & 0x00001f80) << 5) + | ((r & 0x000001f8) << 3) + | ((r & 0x0000001f) << 1) + | ((r & 0x80000000) >> 31); + /* + * Do salting for crypt() and friends, and + * XOR with the permuted key. + */ + f = (r48l ^ r48r) & saltbits; + r48l ^= f ^ *kl++; + r48r ^= f ^ *kr++; + /* + * Do sbox lookups (which shrink it back to 32 bits) + * and do the pbox permutation at the same time. + */ + f = psbox[0][m_sbox[0][r48l >> 12]] + | psbox[1][m_sbox[1][r48l & 0xfff]] + | psbox[2][m_sbox[2][r48r >> 12]] + | psbox[3][m_sbox[3][r48r & 0xfff]]; + /* + * Now that we've permuted things, complete f(). + */ + f ^= l; + l = r; + r = f; + } + r = l; + l = f; + } + /* + * Do final permutation (inverse of IP). + */ + *l_out = fp_maskl[0][l >> 24] + | fp_maskl[1][(l >> 16) & 0xff] + | fp_maskl[2][(l >> 8) & 0xff] + | fp_maskl[3][l & 0xff] + | fp_maskl[4][r >> 24] + | fp_maskl[5][(r >> 16) & 0xff] + | fp_maskl[6][(r >> 8) & 0xff] + | fp_maskl[7][r & 0xff]; + *r_out = fp_maskr[0][l >> 24] + | fp_maskr[1][(l >> 16) & 0xff] + | fp_maskr[2][(l >> 8) & 0xff] + | fp_maskr[3][l & 0xff] + | fp_maskr[4][r >> 24] + | fp_maskr[5][(r >> 16) & 0xff] + | fp_maskr[6][(r >> 8) & 0xff] + | fp_maskr[7][r & 0xff]; + return 0; +} + +char *crypt(char *key, char *setting) { + unsigned long count, salt, l, r0, r1, keybuf[2]; + unsigned char *p, *q; + static unsigned char output[21]; + + if(!des_initialised) + des_init(); + /* + * Copy the key, shifting each character up by one bit + * and padding with zeros. + */ + q = (unsigned char *)keybuf; + while(q - (unsigned char *)keybuf - 8) { + if((*q++ = *key << 1)) + key++; + } + if(des_setkey((unsigned char *)keybuf)) + return NULL; + + /* + * "old"-style: + * setting - 2 bytes of salt + * key - up to 8 characters + */ + count = 25; + + salt = (ascii_to_bin(setting[1]) << 6) + | ascii_to_bin(setting[0]); + + output[0] = setting[0]; + /* + * If the encrypted password that the salt was extracted from + * is only 1 character long, the salt will be corrupted. We + * need to ensure that the output string doesn't have an extra + * NUL in it! + */ + output[1] = setting[1] ? setting[1] : output[0]; + + p = output + 2; + + setup_salt(salt); + /* + * Do it. + */ + if(do_des(0L, 0L, &r0, &r1, count)) + return NULL; + /* + * Now encode the result... + */ + l = (r0 >> 8); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = (r0 << 16) | ((r1 >> 16) & 0xffff); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = r1 << 2; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + *p = 0; + + return output; +} +#endif diff --git a/mbbsd/dice.c b/mbbsd/dice.c new file mode 100644 index 00000000..d64ce63c --- /dev/null +++ b/mbbsd/dice.c @@ -0,0 +1,447 @@ +/* $Id: dice.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +#define DICE_TXT BBSHOME "/etc/dice.txt" +#define DICE_DATA BBSHOME "/etc/dice.data" +#define DICE_WIN BBSHOME "/etc/windice.log" +#define DICE_LOST BBSHOME "/etc/lostdice.log" + +#define B_MAX 500 +#define B_MIN 10 +#define B_COMMON 1 +#define B_TIMES 5 +#define B_THIRD 3 + +extern int usernum; +static int flag[100], value[100]; + +typedef struct dicedata_t { + int mybet; + int mymoney; +} dicedata_t; + +static void set_bingo(int bet[]) { + int i, j = 0, k = 0, m = 0; + + for(i = 0; i < 3; i++) + for(j = 2; j > i; j--) + if(bet[j] < bet[j - 1]) { + m = bet[j]; + bet[j] = bet[j - 1]; + bet[j - 1]=m; + } + + for(i = 0; i < 100; i++) + flag[i] = 0; + + for(i = 0; i < 3; i++) + flag[bet[i]]++; + j = bet[0] + bet[1] + bet[2]; + + if((abs(bet[1] - bet[0]) == 1 && abs(bet[2] - bet[0]) == 2) || + (abs(bet[2] - bet[0]) == 1 && abs(bet[1] - bet[0]) == 2)) + flag[66] = B_TIMES; + + if(j < 10){ + flag[7] = B_COMMON; + for(i = 0; i < 3; i++) + if(bet[i] == 4) + flag[74] = B_TIMES; + } else if(j > 11) { + flag[8] = B_COMMON; + for(i = 0; i < 3; i++) + if(bet[i] == 3) + flag[83]=B_TIMES; + } else + flag[11] = B_THIRD; + + for(i = 0; i < 3; i++) + for(j = i; j < 3; j++) { + m = bet[i]; + k = bet[j]; + if(m != k) + flag[m * 10 + k] = B_TIMES; + } +} + +static int bingo(int mybet) { + return flag[mybet]; +} + +int IsNum(char *a, int n) { + int i; + + for(i = 0; i < n; i++) + if (a[i] > '9' || a[i] < '0' ) + return 0; + return 1; +} + +int IsSNum(char *a) { + int i; + + for(i = 0; a[i]; i++) + if(a[i] > '9' || a[i] < '0') + return 0; + return 1; +} + +static void show_data(void) { + move(0, 0); + prints("\033[31m �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�{\033[m\n"); + prints("\033[45;37m���v�@\033[m\033[31m �x \033[33m[1]��@�I [2]��G�I " + "[3]��T�I [4]��|�I [5]�㤭�I [6]�㤻�I \033[31m �x\033[m\n"); + prints("\033[31m �x \033[33m[7]��p [8]��j " + " \033[31m �x\033[m\n"); + prints("\033[31m �x " + " �x\033[m\n"); + prints("\033[45;37m�߲v�T\033[m\033[31m �x \033[33m[11]�㤤(�`�I�Ƶ���11" + "��10) \033[31m �x\033[m\n"); + prints("\033[31m �x " + " �x\033[m\n"); + prints("\033[45;37m�߲v��\033[m\033[31m �x \033[33m[74]��p�B�|�I [83]��" + "�j�B�T�I [66]��s�� \033[31m �x\033[m\n"); + prints("\033[31m �x " + " �x\033[m\n"); + prints("\033[31m �x \033[33m[12]��@�G�I [13]��@�T�I [14]��@�|�I" + " [15]��@���I [16]��@���I\033[31m �x\033[m\n"); + prints("\033[31m �x \033[33m[23]��G�T�I [24]��G�|�I [25]��G���I" + " [26]��G���I [34]��T�|�I\033[31m �x\033[m\n"); + prints("\033[31m �x \033[33m[35]��T���I [36]��T���I [45]��|���I" + " [46]��|���I [56]�㤭���I\033[31m �x\033[m\n"); + prints("\033[31m �|�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�}\033[m\n"); +} + +static void show_count(int index, int money) { + int i = 0, count = 2, j, k; + + value[index] += money; + move(14,0); + clrtoline(18); + for(i = 1, j = 13; i <= 8; i++, count += 12) { + if(i == 6) { + j = 14; + count = 2; + } + move(j,count); + prints("[%2d]:%d ", i, value[i]); + } + + count = 2; + i = 15; + for(j = 1; j <= 5; j++) + for(k = j + 1; k <= 6; k++, count += 12) { + if(j == 2 && k == 4) { + i = 16; + count = 2; + } else if(j==4 && k==5) { + i = 17; + count = 2; + } + move(i,count); + prints("[%d%d]:%d ", j, k, value[j * 10 + k]); + } + + move(18,2); + prints("[11]:%d",value[11]); + move(18,14); + prints("[66]:%d",value[66]); + move(18,26); + prints("[74]:%d",value[74]); + move(18,38); + prints("[83]:%d",value[83]); +} + +static int check_index(int index) { + int i,tp[] = {1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16, 23, 24, 25, + 26, 34, 35, 36, 45, 46, 56, 66, 74, 83}; + if(index < 0 || index > 100) + return 0; + for(i = 0; i < 27; i++) + if(index == tp[i]) + return 1; + return 0; +} + +extern userec_t cuser; + +static int del(int total, dicedata_t *table) { + int index, money; + char data[10]; + int i; + + while(1) { + do { + move(22,0); + clrtoeol(); + getdata(21, 0, "��J�h�諸�Ʀr(��q���}): ", data, 3, LCECHO); + if(data[0] == 'q' || data[0] == 'Q') + return 0; + } while(!IsNum(data,strlen(data))); + + index = atoi(data); + for(i = 0; i < total; i++) { + if(table[i].mybet == index){ + do { + getdata(21, 0, "�h�ֿ�: ", data, 10, LCECHO); + } while(!IsNum(data,strlen(data))); + money = atoi(data); + if(money>table[i].mymoney) { + move(22,0); + clrtoeol(); + prints("��������"); + i--; + continue; + } + demoney(money); + move(19,0); + clrtoeol(); + prints("�A�{�b�� %u Ptt$��", cuser.money); + table[i].mymoney -= money; + show_count(index, -money); + break; + } + } + } + return 0; +} + +static int IsLegal(char *data) { + int money = atoi(data); + if(IsNum(data,strlen(data)) && money<=B_MAX && money>=B_MIN) + return money; + return 0; +} + +static void show_output(int bet[]) { + int i, j = 10; + + move(12,0); + clrtoline(17); + /* �Ȯɭ��� �]�����Uclrtoline�ǩǪ� */ + for(i = 13; i <= 18; i++) { + move(i,0); + prints(" "); + } + move(12,0); + prints("\033[1;31m �z�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w" + "�w�{\033[m\n\n\n\n\n\n"); + prints("\033[1;31m �|�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w�w" + "�w�}\033[m"); + for(i = 0; i < 3; i++, j += 25) { + switch(bet[i]) { + case 1: + move(13, j);prints("\033[37m�~�w�w�w�w��\033[m"); + move(14, j);prints("\033[37m�x �x\033[m"); + move(15, j);prints("\033[37m�x �� �x\033[m"); + move(16, j);prints("\033[37m�x �x\033[m"); + move(17, j);prints("\033[37m���w�w�w�w��\033[m"); + break; + case 2: + move(13, j);prints("\033[37m�~�w�w�w�w��\033[m"); + move(14, j);prints("\033[37m�x ���x\033[m"); + move(15, j);prints("\033[37m�x �x\033[m"); + move(16, j);prints("\033[37m�x�� �x\033[m"); + move(17, j);prints("\033[37m���w�w�w�w��\033[m"); + break; + case 3: + move(13, j);prints("\033[37m�~�w�w�w�w��\033[m"); + move(14, j);prints("\033[37m�x ���x\033[m"); + move(15, j);prints("\033[37m�x �� �x\033[m"); + move(16, j);prints("\033[37m�x�� �x\033[m"); + move(17, j);prints("\033[37m���w�w�w�w��\033[m"); + break; + case 4: + move(13, j);prints("\033[37m�~�w�w�w�w��\033[m"); + move(14, j);prints("\033[37m�x�� ���x\033[m"); + move(15, j);prints("\033[37m�x �x\033[m"); + move(16, j);prints("\033[37m�x�� ���x\033[m"); + move(17, j);prints("\033[37m���w�w�w�w��\033[m"); + break; + case 5: + move(13, j);prints("\033[37m�~�w�w�w�w��\033[m"); + move(14, j);prints("\033[37m�x�� ���x\033[m"); + move(15, j);prints("\033[37m�x �� �x\033[m"); + move(16, j);prints("\033[37m�x�� ���x\033[m"); + move(17, j);prints("\033[37m���w�w�w�w��\033[m"); + break; + case 6: + move(13, j);prints("\033[37m�~�w�w�w�w��\033[m"); + move(14, j);prints("\033[37m�x�� ���x\033[m"); + move(15, j);prints("\033[37m�x�� ���x\033[m"); + move(16, j);prints("\033[37m�x�� ���x\033[m"); + move(17, j);prints("\033[37m���w�w�w�w��\033[m"); + break; + } + } +} + +#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 + +int dice_main(void) { + char input[10],data[256], ch; + dicedata_t table[256]; + int bet[3], index, money = 0, i, ya = 0, j, total, sig = 0; + FILE *winfp/* , *lostfp */; + + more(DICE_TXT, NA); + reload_money(); + if(cuser.money < 10){ + move(19,0); + prints("\033[1;37m�W�L�Q���A�Ӫ��a~~\033[m"); + pressanykey(); + return 0; + } + + lockreturn0(DICE, LOCK_MULTI); + winfp = fopen(DICE_WIN,"a"); + /*lostfp = fopen(DICE_LOST,"a");*/ + if(!winfp /*|| !lostfp*/) + return 0; + + do { + total = 0; i = 0; + ch = 'y'; + clear(); + show_data(); + for(j = 0; j < 3; j++) + bet[j] = rand() % 6 + 1; + + for(j = 0; j < 100; j++) + value[j] = 0; + + while(1) { + move(19,0); + prints("\033[1;32m�A�{�b��\033[1;31m %u \033[1;32mPtt$��\033[m", + cuser.money); + getdata(20, 0, "\033[1;37m�Ʀr:�[�� d:�h�� s:�}�l�����}\033[m: ", + input, 5, LCECHO); + reload_money(); + if(input[0] != 's' && input[0] != 'd' && cuser.money < 10) { + move(21, 0); + clrtoeol(); + prints("\033[1;37m�W�L�Q���~���~\033[m"); + continue; + } + if(input[0] == 'd' || input[0] == 'D') { + del(i, table); + continue; + } + if(input[0] == 's' || input[0] == 'S') + break; + + if(!IsNum(input,strlen(input))) + continue; + + index=atoi(input); + if(check_index(index) == 0) + continue; +/*��J����loop*/ + while(1) { + if(cuser.money < 10) + break; + getdata(21, 0, "\033[1;32m��h�ֿ��O\033[1;37m(�j��10 �p��500)" + "\033[m: ", input, 9, LCECHO); + if(!(money = IsLegal(input))||input[0] == '0') + continue; + reload_money(); + if(money > cuser.money) + continue; + for(j = 0, sig = 0; j < i; j++) + if(table[j].mybet == index) { + if(table[j].mymoney == B_MAX) + sig = 2; + else if(table[j].mymoney+money>B_MAX) { + sig = 1; + break; + } else { + vice(money,"��l"); + table[j].mymoney += money; + j = -1; + break; + } + } + if(sig == 2) + break; + if(sig == 1) + continue; + if(j != -1) { + bzero((char*)&table[i], sizeof(dicedata_t)); + table[i].mybet = index; + table[i++].mymoney = money; + vice(money,"��l"); + } + break; + } + reload_money(); + move(19,0); + prints("\033[1;32m�A�{�b�� \033[1;31m%u\033[1;32m Ptt$��", + cuser.money); + if(sig != 2) + show_count(index, money); + } + + if(i == 0) { + fclose(winfp); + /*fclose(lostfp);*/ + unlockutmpmode(); + return 0; + } + + show_output(bet); + set_bingo(bet); + + for(j = 0; j < i; j++) { + if(table[j].mymoney <= 0) + continue; + ya = bingo(table[j].mybet); + if(ya == 0) { + /*sprintf(data, "%-15s ��F %-8d $", cuser.userid, + table[j].mymoney); + fprintf(lostfp, "%s\n", data);*/ + continue; + } + demoney(table[j].mymoney * ya + table[j].mymoney); + total += table[j].mymoney * ya; + if (table[j].mymoney * ya > 500){ /* �W�L500�����~��log ���io */ + sprintf(data, "%-15s ��%-2d�ﶵ%-8d���� ���F%d�� �b��:%-8d\n", + cuser.userid,table[j].mybet, + table[j].mymoney, ya, table[j].mymoney * ya); + fputs(data,winfp); + } + ya = 0; + } + + if(total > 0) { + move(21,0); + prints("\033[1;32m�AĹ�F \033[1;31m%d\033[1;32m Ptt$ ��~~" + " \033[m", total); + } else { + move(21,0); + clrtoeol(); + prints("\033[1;32m�u�i�� �U���A�ӸI�I�B��a\033[m"); + } + + move(19,0); + clrtoeol(); + prints("\033[1;32m�A�{�b�� \033[1;31m%u\033[1;32m Ptt$��\033[m", + cuser.money); + + getdata(23, 0, "\033[1;32m�~��İ�[\033[1;37my/n\033[1;32m]\033[m: ", + input, 2, LCECHO); + } while(input[0] != 'n' && input[0] != 'N'); + fclose(winfp); + /*fclose(lostfp);*/ + unlockutmpmode(); + return 0; +} diff --git a/mbbsd/edit.c b/mbbsd/edit.c new file mode 100644 index 00000000..19f437af --- /dev/null +++ b/mbbsd/edit.c @@ -0,0 +1,2256 @@ +/* $Id: edit.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "config.h" +#include "common.h" +#include "modes.h" +#include "perm.h" +#include "proto.h" + +#define WRAPMARGIN (511) + +typedef struct textline_t { + struct textline_t *prev; + struct textline_t *next; + int len; + char data[WRAPMARGIN + 1]; +} textline_t; + +extern int current_font_type; +extern char *str_author1; +extern char *str_author2; +extern int t_lines, t_columns; /* Screen size / width */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char quote_file[80]; +extern char quote_user[80]; +extern int curredit; +extern unsigned int currbrdattr; +extern char currboard[]; /* name of currently selected board */ +extern char *str_reply; +extern char *str_post1; +extern char *str_post2; +extern char *BBSName; +extern char fromhost[]; +extern unsigned int currstat; +extern crosspost_t postrecord; +extern userinfo_t *currutmp; +extern int KEY_ESC_arg; +extern char reset_color[]; +extern char trans_buffer[256]; + +#define KEEP_EDITING -2 +#define BACKUP_LIMIT 100 +#define SCR_WIDTH 80 + +enum { + NOBODY, MANAGER, SYSOP +}; + +static textline_t *firstline = NULL; +static textline_t *lastline = NULL; +static textline_t *currline = NULL; +static textline_t *blockline = NULL; +static textline_t *top_of_win = NULL; +static textline_t *deleted_lines = NULL; + +extern int local_article; +extern char real_name[20]; +static char line[WRAPMARGIN + 2]; +static int ifuseanony=0; +static int currpnt, currln, totaln; +static int curr_window_line; +static int redraw_everything; +static int insert_character; +static int my_ansimode; +static int raw_mode; +static int edit_margin; +static int blockln = -1; +static int blockpnt; +static int prevln = -1; +static int prevpnt; +static int line_dirty; +static int indent_mode; +static int insert_c = ' '; + +static char fp_bak[] = "bak"; + +char save_title[STRLEN]; + +/* �O����z�P�s��B�z */ +static void indigestion(i) { + fprintf(stderr, "�Y������ %d\n", i); +} + +/* Thor: ansi �y���ഫ for color �s��Ҧ� */ +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(ch)) + tmp++; + if(ch) + tmp++; + continue; + } + if(ansix <= 0) + break; + tmp++; + ansix--; + } + return tmp - data; +} + +static int n2ansi(int nx, textline_t * line) { + register int 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(ch)) + tmp++; + if(ch) + tmp++; + continue; + } + if(tmp >= nxp) + break; + tmp++; + ansix++; + } + return ansix; +} + +/* �ù��B�z�G���U�T���B��ܽs�褺�e */ +static void edit_msg() { + static char *edit_mode[2] = {"���N", "���J"}; + register int n = currpnt; + + if(my_ansimode) /* Thor: �@ ansi �s�� */ + n = n2ansi(n, currline); + n++; + move(b_lines, 0); + clrtoeol(); + prints("\033[%sm �s��峹 \033[31;47m (Ctrl-Z)\033[30m���U���� " + "\033[31;47m(^G)\033[30m���J�Ϥ�w \033[31m(^X,^Q)" + "\033[30m���}��%s�x%c%c%c%c�� %3d:%3d \033[m", + "37;44", + edit_mode[insert_character], + my_ansimode ? 'A' : 'a', indent_mode ? 'I' : 'i', + 'P' , raw_mode ? 'R' : 'r', + currln + 1, n); +} + +static textline_t *back_line(textline_t *pos, int num) { + while(num-- > 0) { + register textline_t *item; + + if(pos && (item = pos->prev)) { + pos = item; + currln--; + } + } + return pos; +} + +static textline_t *forward_line(textline_t *pos, int num) { + while(num-- > 0) { + register textline_t *item; + + if(pos && (item = pos->next)) { + pos = item; + currln++; + } + } + return pos; +} + +static int getlineno() { + int cnt = 0; + textline_t *p = currline; + + while(p && (p != top_of_win)) { + cnt++; + p = p->prev; + } + return cnt; +} + +static char *killsp(char *s) { + while(*s == ' ') + s++; + return s; +} + +static textline_t *alloc_line() { + register textline_t *p; + + if((p = (textline_t *)malloc(sizeof(textline_t)))) { + memset(p, 0, sizeof(textline_t)); + return p; + } + + indigestion(13); + abort_bbs(0); + return NULL; +} + +/* append p after line in list. keeps up with last line */ +static void append(textline_t *p, textline_t *line) { + register textline_t *n; + + if((p->next = n = line->next)) + n->prev = p; + else + lastline = p; + line->next = p; + p->prev = line; +} + +/* + delete_line deletes 'line' from the list, + and maintains the lastline, and firstline pointers. +*/ + +static void delete_line(textline_t *line) { + register textline_t *p = line->prev; + register textline_t *n = line->next; + + if(!p && !n) { + line->data[0] = line->len = 0; + return; + } + if(n) + n->prev = p; + else + lastline = p; + if(p) + p->next = n; + else + firstline = n; + strcat(line->data, "\n"); + line->prev = deleted_lines; + deleted_lines = line; + totaln--; +} + +static int ask(char *prompt) { + int ch; + + move (0, 0); + clrtoeol (); + standout (); + prints ("%s", prompt); + standend (); + ch = igetkey (); + move (0, 0); + clrtoeol (); + return (ch); +} + +static int indent_spcs() { + textline_t* p; + int spcs; + + if(!indent_mode) + return 0; + + for(p = currline; p; p = p->prev) { + for(spcs = 0; p->data[spcs] == ' '; ++spcs); + if (p->data[spcs]) + return spcs; + } + return 0; +} + +/* split 'line' right before the character pos */ +static void split(textline_t *line, int pos) { + if(pos <= line->len) { + register textline_t *p = alloc_line(); + register char *ptr; + int spcs = indent_spcs(); + + totaln++; + + p->len = line->len - pos + spcs; + line->len = pos; + + memset(p->data, ' ', spcs); + p->data[spcs] = 0; + strcat(p->data, (ptr = line->data + pos)); + ptr[0] = '\0'; + append(p, line); + if(line == currline && pos <= currpnt) { + currline = p; + if(pos == currpnt) + currpnt = spcs; + else + currpnt -= pos; + curr_window_line++; + currln++; + } + redraw_everything = YEA; + } +} + +static void insert_char(int ch) { + register textline_t *p = currline; + register int i = p->len; + register char *s; + int wordwrap = YEA; + + if(currpnt > i) { + indigestion(1); + return; + } + if(currpnt < i && !insert_character) { + p->data[currpnt++] = ch; + /* Thor: ansi �s��, �i�Hoverwrite, ���\�� ansi code */ + if(my_ansimode) + currpnt = ansi2n(n2ansi(currpnt, p),p); + } else { + while(i >= currpnt) { + p->data[i + 1] = p->data[i]; + i--; + } + p->data[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); + } + 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++; + } + } +} + +static void insert_string(char *str) { + int ch; + + while((ch = *str++)) { + if(isprint2(ch) || ch == '\033') + insert_char(ch); + else if(ch == '\t') { + do { + insert_char(' '); + } while(currpnt & 0x7); + } else if(ch == '\n') + split(currline, currpnt); + } +} + +static int undelete_line() { + textline_t* p = deleted_lines; + textline_t* currline0 = currline; + textline_t* top_of_win0 = top_of_win; + int currpnt0 = currpnt; + int currln0 = currln; + int curr_window_line0 = curr_window_line; + int indent_mode0 = indent_mode; + + if(!deleted_lines) + return 0; + + indent_mode = 0; + insert_string(deleted_lines->data); + indent_mode = indent_mode0; + deleted_lines = deleted_lines->prev; + free(p); + + currline = currline0; + top_of_win = top_of_win0; + currpnt = currpnt0; + currln = currln0; + curr_window_line = curr_window_line0; + return 0; +} + +/* + 1) lines were joined and one was deleted + 2) lines could not be joined + 3) next line is empty + returns false if: + 1) Some of the joined line wrapped +*/ +static int join(textline_t *line) { + register textline_t *n; + register int ovfl; + + if(!(n = line->next)) + return YEA; + if(!*killsp(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); + return YEA; + } else { + register char *s; + + 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 + n->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++; + } + } + return NA; + } +} + +static void delete_char() { + register int len; + + if((len = currline->len)) { + register int i; + register char *s; + + if(currpnt >= len) { + indigestion(1); + return; + } + for(i = currpnt, s = currline->data + i; i != len; i++, s++) + s[0] = s[1]; + currline->len--; + } +} + +static void load_file(FILE *fp) { + int indent_mode0 = indent_mode; + + indent_mode = 0; + while(fgets(line, WRAPMARGIN + 2, fp)) + insert_string(line); + fclose(fp); + 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(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, 4, LCECHO); + if(*ans != 'n' && (fp = fopen(fp_tmpbuf, "r"))) { + prevln = currln; + prevpnt = currpnt; + load_file(fp); + while(curr_window_line >= b_lines) { + curr_window_line--; + top_of_win = top_of_win->next; + } + } +} + +static void write_tmpbuf() { + FILE *fp; + char fp_tmpbuf[80], ans[4]; + textline_t *p; + + 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, 4, LCECHO); + + if(ans[0] == 'q') + return; + } + + if((fp = fopen(fp_tmpbuf, (ans[0] == 'w' ? "w" : "a+")))) { + for(p = firstline; p; p = p->next) { + if(p->next || p->data[0]) + fprintf(fp, "%s\n", p->data); + } + fclose(fp); + } +} + +static void erase_tmpbuf() { + 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, 4, LCECHO); + if(*ans == 'y') + unlink(fp_tmpbuf); +} + +/* �s�边�۰ʳƥ� */ +void auto_backup() { + if(currline) { + FILE *fp; + textline_t *p, *v; + char bakfile[64]; + int count = 0; + + setuserfile(bakfile, fp_bak); + if((fp = fopen(bakfile, "w"))) { + for(p = firstline; p != NULL && count < 512; p = v,count++) { + v = p->next; + fprintf(fp, "%s\n", p->data); + free(p); + } + fclose(fp); + } + currline = NULL; + } +} + +void restore_backup() { + 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(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 do_quote() { + int op; + char buf[256]; + + 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 = indent_mode; + + fgets(buf, 256, 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, ' '); + str[0] = '\0'; + } + } else + ptr = quote_user; + + indent_mode = 0; + insert_string("�� �ޭz�m"); + insert_string(ptr); + insert_string("�n���ʨ��G\n"); + + if(op != 'a') /* �h�� header */ + while(fgets(buf, 256, inf) && buf[0] != '\n'); + + if(op == 'a') + while(fgets(buf, 256, inf)) { + insert_char(':'); + insert_char(' '); + insert_string(Ptt_prints(buf,STRIP_ALL)); + } + else if(op == 'r') + while(fgets(buf, 256, inf)) + insert_string(Ptt_prints(buf,NO_RELOAD)); + else { + if(curredit & EDIT_LIST) /* �h�� mail list �� header */ + while (fgets(buf, 256, inf) && (!strncmp(buf, "�� ", 3))); + while(fgets(buf, 256, inf)) { + if(!strcmp(buf, "--\n")) + break; + if(!garbage_line(buf)) { + insert_char(':'); + insert_char(' '); + insert_string(Ptt_prints(buf,STRIP_ALL)); + } + } + } + indent_mode = indent_mode0; + fclose(inf); + } + } +} + +/* �f�d user �ި����ϥ� */ +static int check_quote() { + register textline_t *p = 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" + "\033[1;33m1) �W�[�@�Ǥ峹 �� 2) �R�������n���ި�\033[m"); + { + char ans[4]; + + getdata(12, 12, "(E)�~��s�� (W)�j��g�J�H[E] ", ans, 4, LCECHO); + if(ans[0] == 'w') + return 0; + } + return 1; + } + return 0; +} + +/* �ɮ׳B�z�GŪ�ɡB�s�ɡB���D�Bñ�W�� */ +static void read_file(char *fpath) { + FILE *fp; + + if((fp = fopen(fpath, "r")) == NULL) { + if((fp = fopen(fpath, "w+"))) { + fclose(fp); + return; + } + indigestion(4); + abort_bbs(0); + } + load_file(fp); +} + +extern userec_t cuser; + +void write_header(FILE *fp) { + time_t now = time(0); + + if(curredit & EDIT_MAIL || curredit & EDIT_LIST) { + fprintf(fp, "%s %s (%s)\n", str_author1, cuser.userid, +#if defined(REALINFO) && defined(MAIL_REALNAMES) + cuser.realname +#else + cuser.username +#endif + ); + } else { + char *ptr; + struct { + char author[IDLEN + 1]; + char board[IDLEN + 1]; + char title[66]; + time_t date; /* last post's date */ + int number; /* post number */ + } postlog; + + strcpy(postlog.author, cuser.userid); + 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, 12, DOECHO); + else + getdata(3, 0, "�п�J�A�Q�Ϊ�ID�A�]�i������[Enter]�ϥέ�ID�G", + real_name, 12, DOECHO); + if(!real_name[0] && defanony) { + strcpy(real_name, "Anonymous"); + strcpy(postlog.author, real_name); + ifuseanony = 1; + } else { + if(!strcmp("r",real_name) || (!defanony && !real_name[0])) + sprintf(postlog.author,"%s",cuser.userid); + else { + sprintf(postlog.author,"%s.",real_name); + ifuseanony=1; + } + } + } +#endif + strcpy(postlog.board, currboard); + ptr = save_title; + if(!strncmp(ptr, str_reply, 4)) + ptr += 4; + strncpy(postlog.title, ptr, 65); + 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.username : + "�q�q�ڬO�� ? ^o^"), + local_article ? str_post2 : str_post1, currboard); + } else { + fprintf(fp, "%s %s (%s) %s %s\n", str_author1, cuser.userid, +#if defined(REALINFO) && defined(POSTS_REALNAMES) + cuser.realname, +#else + cuser.username, +#endif + local_article ? str_post2 : str_post1, currboard); + } +#else /* HAVE_ANONYMOUS */ + fprintf(fp, "%s %s (%s) %s %s\n", str_author1, cuser.userid, +#if defined(REALINFO) && defined(POSTS_REALNAMES) + cuser.realname, +#else + cuser.username, +#endif + local_article ? str_post2 : str_post1, currboard); +#endif /* HAVE_ANONYMOUS */ + + } + save_title[72] = '\0'; + fprintf(fp, "���D: %s\n�ɶ�: %s\n", save_title, ctime(&now)); +} + +void addsignature(FILE *fp, int ifuseanony) { + FILE *fs; + int i; + char buf[WRAPMARGIN + 1]; + char fpath[STRLEN]; + + static char msg[] = "�п��ñ�W�� (1-9, 0=���[)[0]: "; + char ch; + + if(!strcmp(cuser.userid,STR_GUEST)) { + fprintf(fp, "\n--\n�� �o�H�� :" BBSNAME "(" MYHOSTNAME + ") \n�� From: %s\n", fromhost); + return; + } + if(!ifuseanony) { + i = showsignature(fpath); + msg[27] = ch = '0' | (cuser.uflag & SIG_FLAG); + getdata(0, 0, msg, buf, 4, DOECHO); + + if(ch != buf[0] && buf[0] >= '0' && buf[0] <= '9') { + ch = buf[0]; + cuser.uflag = (cuser.uflag & ~SIG_FLAG) | (ch & SIG_FLAG); + } + + if(ch != '0') { + fpath[i] = ch; + 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); + } + } + } +#ifdef HAVE_ORIGIN +#ifdef HAVE_ANONYMOUS + if(ifuseanony) + fprintf(fp, "\n--\n�� �o�H��: " BBSNAME "(" MYHOSTNAME + ") \n�� From: %s\n", "�ʦW�ѨϪ��a"); + else { + char temp[32]; + + strncpy(temp, fromhost, 31); + temp[32] = '\0'; + fprintf(fp, "\n--\n�� �o�H��: " BBSNAME "(" MYHOSTNAME + ") \n�� From: %s\n", temp); + } +#else + strncpy (temp,fromhost,15); + fprintf(fp, "\n--\n�� �o�H��: " BBSNAME "(" MYHOSTNAME + ") \n�� From: %s\n", temp); +#endif +#endif +} + +static int +write_file(char *fpath, int saveheader, int *islocal) { + time_t now; + 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"); + if(currstat == SMAIL) + msg = "[S]�x�s (A)��� (T)����D (E)�~�� (R/W/D)Ū�g�R�Ȧs�ɡH"; + else if(local_article) + msg = "[L]�����H�� (S)�x�s (A)��� (T)����D (E)�~�� " + "(R/W/D)Ū�g�R�Ȧs�ɡH"; + else + msg = "[S]�x�s (L)�����H�� (A)��� (T)����D (E)�~�� " + "(R/W/D)Ū�g�R�Ȧs�ɡH"; + getdata(1, 0, msg, ans, 3, LCECHO); + + switch(ans[0]) { + case 'a': + outs("�峹\033[1m �S�� \033[m�s�J"); + safe_sleep(1); + aborted = -1; + break; + case 'r': + read_tmpbuf(-1); + case 'e': + return KEEP_EDITING; + case 'w': + write_tmpbuf(); + return KEEP_EDITING; + case 'd': + erase_tmpbuf(); + return KEEP_EDITING; + case 't': + move(3, 0); + prints("�¼��D�G%s", save_title); + strcpy(ans,save_title); + if(getdata_buf(4, 0, "�s���D�G", ans, TTLEN, DOECHO)) + strcpy(save_title, ans); + return KEEP_EDITING; + case 's': + if(!HAS_PERM(PERM_LOGINOK)) { + local_article = 1; + move(2, 0); + prints("�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) { + sethomepath(fpath, cuser.userid); + strcpy(fpath, tempnam(fpath, "ve_")); + } + + if((fp = fopen(fpath, "w")) == NULL) { + indigestion(5); + abort_bbs(0); + } + if(saveheader) + write_header(fp); + } + + for(p = firstline; p; p = v) { + v = p->next; + if(!aborted) { + msg = p->data; + if(v || msg[0]) { + trim(msg); + + line++; + if(currstat == POSTING && po) { + saveheader = str_checksum(msg); + if(saveheader) { + if(postrecord.checksum[po] == saveheader) { + po++; + if(po > 3) { + postrecord.times++; + po =0; + } + } else + po = 1; + if(currstat == POSTING && line >= totaln/2 && + sum < 3) { + checksum[sum++] = saveheader; + } + } + } +#ifdef SUPPORT_GB + if(current_font_type == TYPE_GB) + { + fprintf(fp, "%s\n", hc_convert_str(msg, HC_GBtoBIG, HC_DO_SINGLE)); + } + else +#endif + fprintf(fp, "%s\n", msg); + } + } + free(p); + } + currline = NULL; + + if(postrecord.times > MAX_CROSSNUM - 1) + anticrosspost(); + + if(po && sum == 3) { + memcpy(&postrecord.checksum[1], checksum, sizeof(int) * 3); + postrecord.times =0; + } + if(!aborted) { + if(islocal) + *islocal = (local_article == 1); + if(currstat == POSTING || currstat == SMAIL) + addsignature(fp,ifuseanony); + else if(currstat == REEDIT +#ifndef ALL_REEDIT_LOG + && strcmp(currboard, "SYSOP") == 0 +#endif + ) + { + time(&now); + ptime = localtime(&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); + if(local_article && (currstat == POSTING)) + return 0; + return 0; + } + return aborted; +} + + +static void display_buffer() { + register textline_t *p; + register int i; + int inblock; + char buf[WRAPMARGIN + 2]; + int min, max; + + if(currpnt > blockpnt) { + min = blockpnt; + max = currpnt; + } else { + min = currpnt; + max = blockpnt; + } + + for(p = top_of_win, i = 0; i < b_lines; i++) { + move(i, 0); + clrtoeol(); + if(blockln >= 0 && + ((blockln <= currln && blockln <= (currln - curr_window_line + i) && + (currln - curr_window_line + i) <= currln) || + (currln <= (currln - curr_window_line + i) && + (currln - curr_window_line + i) <= blockln))) { + outs("\033[7m"); + inblock = 1; + } else + inblock = 0; + if(p) { + if(my_ansimode) + if(currln == blockln && p == currline && max > min) { + outs("\033[m"); + strncpy(buf, p->data, min); + buf[min] = 0; + outs(buf); + outs("\033[7m"); + strncpy(buf, p->data + min, max - min); + buf[max - min] = 0; + outs(buf); + outs("\033[m"); + outs(p->data + max); + } else + outs(p->data); + else if(currln == blockln && p == currline && max > min) { + outs("\033[m"); + strncpy(buf, p->data, min); + buf[min] = 0; + edit_outs(buf); + outs("\033[7m"); + strncpy(buf, p->data + min, max - min); + buf[max - min] = 0; + edit_outs(buf); + outs("\033[m"); + edit_outs(p->data + max); + } else + edit_outs(&p->data[edit_margin]); + p = p->next; + if(inblock) + outs("\033[m"); + } else + outch('~'); + } + edit_msg(); +} + +static void goto_line(int lino) { + char buf[10]; + + if(lino > 0 || + (getdata(b_lines - 1, 0, "���ܲĴX��:", buf, 10, DOECHO) && + sscanf(buf, "%d", &lino) && lino > 0)) { + textline_t* p; + + prevln = currln; + prevpnt = currpnt; + p = firstline; + currln = lino - 1; + + while(--lino && p->next) + p = p->next; + + if(p) + currline = p; + else { + currln = totaln; + currline = lastline; + } + currpnt = 0; + if(currln < 11) { + top_of_win = firstline; + curr_window_line = currln; + } else { + int i; + + curr_window_line = 11; + for(i = curr_window_line; i; i--) + p = p->prev; + top_of_win = p; + } + } + redraw_everything = YEA; +} + +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; +} + +/* + mode: + 0: prompt + 1: forward + -1: backward +*/ +static void search_str(int mode) { + static char str[80]; + typedef char* (*FPTR)(); + static FPTR fptr; + char ans[4] = "n"; + + if(!mode) { + if(getdata_buf(b_lines - 1, 0,"[�j�M]����r:",str, 65, DOECHO)) + if(*str) { + if(getdata(b_lines - 1, 0, "�Ϥ��j�p�g(Y/N/Q)? [N] ", + ans, 4, LCECHO) && *ans == 'y') + fptr = strstr; + else + fptr = strcasestr; + } + } + + if(*str && *ans != 'q') { + textline_t* p; + char *pos = NULL; + int lino; + + if(mode >= 0) { + for(lino = currln, p = currline; p; p = p->next, lino++) + if((pos = fptr(p->data + (lino == currln ? currpnt + 1 : 0), + str)) && (lino != currln || + pos - p->data != currpnt)) + break; + } else { + for(lino = currln, p = currline; p; p = p->prev, lino--) + if((pos = fptr(p->data, str)) && + (lino != currln || pos - p->data != currpnt)) + break; + } + if(pos) { + prevln = currln; + prevpnt = currpnt; + currline = p; + currln = lino; + currpnt = pos - p->data; + if(lino < 11) { + top_of_win = firstline; + curr_window_line = currln; + } else { + int i; + + curr_window_line = 11; + for(i = curr_window_line; i; i--) + p = p->prev; + top_of_win = p; + } + redraw_everything = YEA; + } + } + if(!mode) + redraw_everything = YEA; +} + +static void match_paren() { + static char parens[] = "()[]{}"; + int type; + int parenum = 0; + char *ptype; + textline_t* p; + int lino; + int c, i = 0; + + if(!(ptype = strchr(parens, currline->data[currpnt]))) + return; + + type = (ptype - parens) / 2; + parenum += ((ptype - parens) % 2) ? -1 : 1; + + if(parenum > 0) { + for(lino = currln, p = currline; p; p = p->next, lino++) { + lino = lino; + for(i = (lino == currln) ? currpnt + 1 : 0; + i < strlen(p->data); i++) + if(p->data[i] == '/' && p->data[++i] == '*') { + ++i; + while(1) { + while(i < strlen(p->data) - 1 && + !(p->data[i] == '*' && p->data[i + 1] == '/')) + i++; + if(i >= strlen(p->data) - 1 && p->next) { + p = p->next; + ++lino; + i = 0; + } else + break; + } + } else if((c = p->data[i]) == '\'' || c == '"') { + while(1) { + while(i < (int)(strlen(p->data) - 1)) + if(p->data[++i] == '\\' && i < strlen(p->data) - 2) + ++i; + else if(p->data[i] == c) + goto end_quote; + if(i >= strlen(p->data) - 1 && p->next) { + p = p->next; + ++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 = currln, p = currline; p; p = p->prev, lino--) + for(i = (lino == currln) ? currpnt - 1 : strlen(p->data) - 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; + --lino; + i = strlen(p->data) - 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; + --lino; + i = strlen(p->data); + } 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 = currln - curr_window_line; + int bottom = currln - curr_window_line + b_lines - 1; + + currpnt = i; + currline = p; + curr_window_line += lino - currln; + currln = lino; + + if(lino < top || lino > bottom) { + if(lino < 11) { + top_of_win = firstline; + curr_window_line = currln; + } else { + int i; + + curr_window_line = 11; + for(i = curr_window_line; i; i--) + p = p->prev; + top_of_win = p; + } + redraw_everything = YEA; + } + } +} + +static void block_del(int hide) { + if(blockln < 0) { + blockln = currln; + blockpnt = currpnt; + blockline = currline; + } else { + char fp_tmpbuf[80]; + FILE* fp; + textline_t *begin, *end, *p; + char tmpfname[10] = "buf.0"; + char ans[6] = "w+n"; + + move(b_lines - 1, 0); + clrtoeol(); + if(hide == 1) + tmpfname[4] = 'q'; + else if(!hide && !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') + tmpfname[4] = 'q'; + if('1' <= tmpfname[4] && tmpfname[4] <= '9') { + setuserfile(fp_tmpbuf, tmpfname); + if(tmpfname[4] != '5' && dashf(fp_tmpbuf)) { + more(fp_tmpbuf, NA); + getdata(b_lines - 1, 0, "�Ȧs�ɤw����� (A)���[ (W)�мg " + "(Q)�����H[W] ", ans, 4, LCECHO); + if(*ans == 'q') + tmpfname[4] = 'q'; + else if(*ans != 'a') + *ans = 'w'; + } + if(tmpfname[4] != '5') { + getdata(b_lines - 1, 0, "�R���϶�(Y/N)?[N] ", + ans + 2, 4, LCECHO); + if(ans[2] != 'y') + ans[2] = 'n'; + } + } else if(hide != 3) + ans[2] = 'y'; + + tmpfname[5] = ans[1] = ans[3] = 0; + if(tmpfname[4] != 'q') { + if(currln >= blockln) { + begin = blockline; + end = currline; + if(ans[2] == 'y' && !(begin == end && currpnt != blockpnt)) { + curr_window_line -= (currln - blockln); + if(curr_window_line < 0) { + curr_window_line = 0; + if(end->next) + (top_of_win = end->next)->prev = begin->prev; + else + top_of_win = (lastline = begin->prev); + } + currln -= (currln - blockln); + } + } else { + begin = currline; + end = blockline; + } + if(ans[2] == 'y' && !(begin == end && currpnt != blockpnt)) { + if(begin->prev) + begin->prev->next = end->next; + else if(end->next) + top_of_win = firstline = end->next; + else { + currline = top_of_win = firstline = + lastline = alloc_line(); + currln = curr_window_line = edit_margin = 0; + } + + if(end->next) + (currline = end->next)->prev = begin->prev; + else if(begin->prev) { + currline = (lastline = begin->prev); + currln--; + if(curr_window_line > 0) + curr_window_line--; + } + } + + setuserfile(fp_tmpbuf, tmpfname); + if((fp = fopen(fp_tmpbuf, ans))) { + if(begin == end && currpnt != blockpnt) { + char buf[WRAPMARGIN + 2]; + + if(currpnt > blockpnt) { + strcpy(buf, begin->data + blockpnt); + buf[currpnt - blockpnt] = 0; + } else { + strcpy(buf, begin->data + currpnt); + buf[blockpnt - currpnt] = 0; + } + fputs(buf, fp); + } else { + for(p = begin; p != end; p = p->next) + fprintf(fp, "%s\n", p->data); + fprintf(fp, "%s\n", end->data); + } + fclose(fp); + } + + if(ans[2] == 'y') { + if(begin == end && currpnt != blockpnt) { + int min, max; + + if(currpnt > blockpnt) { + min = blockpnt; + max = currpnt; + } else { + min = currpnt; + max = blockpnt; + } + strcpy(begin->data + min, begin->data + max); + begin->len -= max - min; + currpnt = min; + } else { + for(p = begin; p != end; totaln--) + free((p = p->next)->prev); + free(end); + totaln--; + currpnt = 0; + } + } + } + blockln = -1; + redraw_everything = YEA; + } +} + +static void block_shift_left() { + textline_t *begin, *end, *p; + + if(currln >= blockln) { + begin = blockline; + end = currline; + } else { + begin = currline; + end = blockline; + } + p = begin; + while(1) { + if(p->len) { + strcpy(p->data, p->data + 1); + --p->len; + } + if(p == end) + break; + else + p = p->next; + } + if(currpnt > currline->len) + currpnt = currline->len; + redraw_everything = YEA; +} + +static void block_shift_right() { + textline_t *begin, *end, *p; + + if(currln >= blockln) { + begin = blockline; + end = currline; + } else { + begin = currline; + end = blockline; + } + p = begin; + while(1) { + if(p->len < WRAPMARGIN) { + int i = p->len + 1; + + while(i--) + p->data[i + 1] = p->data[i]; + p->data[0] = insert_character ? ' ' : insert_c; + ++p->len; + } + if(p == end) + break; + else + p = p->next; + } + if(currpnt > currline->len) + currpnt = currline->len; + redraw_everything = YEA; +} + +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() { + textline_t *begin, *end, *p; + + if(currln >= blockln) { + begin = blockline; + end = currline; + } else { + begin = currline; + end = blockline; + } + p = begin; + while(1) { + transform_to_color(p->data); + if(p == end) + break; + else + p = p->next; + } + block_del(1); +} + +/* �s��B�z�G�D�{���B��L�B�z */ +int vedit(char *fpath, int saveheader, int *islocal) { + FILE *fp1; + char last = 0, buf[200]; /* the last key you press */ + int ch, foo; + int lastindent = -1; + int last_margin; + int mode0 = currutmp->mode; + int destuid0 = currutmp->destuid; + unsigned int money=0; + unsigned short int interval=0; + time_t now=0,th; + + textline_t* firstline0 = firstline; + textline_t* lastline0 = lastline; + textline_t* currline0 = currline; + textline_t* blockline0 = blockline; + textline_t* top_of_win0 = top_of_win; + int local_article0 = local_article; + int currpnt0 = currpnt; + int currln0 = currln; + int totaln0 = totaln; + int curr_window_line0 = curr_window_line; + int insert_character0 = insert_character; + int my_ansimode0 = my_ansimode; + int edit_margin0 = edit_margin; + int blockln0 = blockln, count=0, tin=0; + + currutmp->mode = EDITING; + currutmp->destuid = currstat; + insert_character = redraw_everything = 1; + prevln = blockln = -1; + + line_dirty = currpnt = totaln = my_ansimode = 0; + currline = top_of_win = firstline = lastline = alloc_line(); + + if(*fpath) + read_file(fpath); + + if(*quote_file) { + do_quote(); + *quote_file = '\0'; + if(quote_file[79] == 'L') + local_article = 1; + } + + currline = firstline; + currpnt = currln = curr_window_line = edit_margin = last_margin = 0; + + while(1) { + if(redraw_everything || blockln >= 0) { + display_buffer(); + redraw_everything = NA; + } + if(my_ansimode) + ch = n2ansi(currpnt, currline); + else + ch = currpnt - edit_margin; + move(curr_window_line, ch); + if(!line_dirty && strcmp(line, currline->data)) + strcpy(line, currline->data); + ch = igetkey(); + /* jochang debug */ + if((interval = (unsigned short int)((th = currutmp->lastact) - now))) { + now = th; + if((char)ch != last) { + money++; + last = (char)ch; + } + } + if(interval && interval == tin) + count++; + else + { + count=0; + tin = interval; + } + /* �s��240��interval�@�� , �����O�b�İ] */ + if(count >= 240) { + sprintf(buf, "\033[1;33;46m%s\033[37m�b\033[37;45m%s" + "\033[37m�O�H�k�ȿ� , %s\033[m", cuser.userid, + currboard,ctime(&now)); + log_file ("etc/illegal_money",buf); + money = 0 ; + post_violatelaw(cuser.userid, "Ptt �t��ĵ��", "�H�k�ȿ�", "�������k�ұo"); + mail_violatelaw(cuser.userid, "Ptt �t��ĵ��", "�H�k�ȿ�", "�������k�ұo"); +// demoney(10000); +// abort_bbs(0); + } + + if(raw_mode) + switch (ch) { + case Ctrl('S'): + case Ctrl('Q'): + case Ctrl('T'): + continue; + break; + } + if(ch < 0x100 && isprint2(ch)) { + insert_char(ch); + lastindent = -1; + line_dirty = 1; + } else { + if(ch == Ctrl('P') || ch == KEY_UP || ch == KEY_DOWN || + ch == Ctrl('N')) { + if(lastindent == -1) + lastindent = currpnt; + } else + 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; + case '-': + ch = Ctrl('_'); + break; + case 's': + ch = Ctrl('S'); + break; + } + + switch(ch) { + case Ctrl('X'): /* Save and exit */ + foo = write_file(fpath, saveheader, islocal); + if(foo != KEEP_EDITING) { + currutmp->mode = mode0; + currutmp->destuid = destuid0; + firstline = firstline0; + lastline = lastline0; + currline = currline0; + blockline = blockline0; + top_of_win = top_of_win0; + local_article = local_article0; + currpnt = currpnt0; + currln = currln0; + totaln = totaln0; + curr_window_line = curr_window_line0; + insert_character = insert_character0; + my_ansimode = my_ansimode0; + edit_margin = edit_margin0; + blockln = blockln0; + if(!foo) + return money; + else + return foo; + } + line_dirty = 1; + redraw_everything = YEA; + break; + case Ctrl('W'): + if(blockln >= 0) + block_del(2); + line_dirty = 1; + break; + case Ctrl('Q'): /* Quit without saving */ + ch = ask("���������x�s (Y/N)? [N]: "); + if(ch == 'y' || ch == 'Y') { + currutmp->mode = mode0; + currutmp->destuid = destuid0; + firstline = firstline0; + lastline = lastline0; + currline = currline0; + blockline = blockline0; + top_of_win = top_of_win0; + local_article = local_article0; + currpnt = currpnt0; + currln = currln0; + totaln = totaln0; + curr_window_line = curr_window_line0; + insert_character = insert_character0; + my_ansimode = my_ansimode0; + edit_margin = edit_margin0; + blockln = blockln0; + return -1; + } + line_dirty = 1; + redraw_everything = YEA; + break; + case Ctrl('C'): + ch = insert_character; + insert_character = redraw_everything = YEA; + if(!my_ansimode) + insert_string(reset_color); + else { + char ans[4]; + move(b_lines - 2, 55); + outs("\033[1;33;40mB\033[41mR\033[42mG\033[43mY\033[44mL" + "\033[45mP\033[46mC\033[47mW\033[m"); + if(getdata(b_lines - 1, 0, + "�п�J �G��/�e��/�I��[���`�զr�©�][0wb]�G", + ans, 4, LCECHO)) { + char t[] = "BRGYLPCW"; + char color[15]; + char *tmp, *apos = ans; + int fg, bg; + + strcpy(color, "\033["); + if(isdigit(*apos)) { + sprintf(color, "%s%c", color, *(apos++)); + if(*apos) + sprintf(color, "%s;", 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); + } + sprintf(color, "%sm", color); + insert_string(color); + } else + insert_string(reset_color); + } + insert_character = ch; + line_dirty = 1; + break; + case KEY_ESC: + line_dirty = 0; + switch(KEY_ESC_arg) { + case 'U': + t_users(); + redraw_everything = YEA; + line_dirty = 1; + break; + case 'i': + t_idle(); + redraw_everything = YEA; + line_dirty = 1; + break; + case 'n': + search_str(1); + break; + case 'p': + search_str(-1); + break; + case 'L': + case 'J': + goto_line(0); + 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'); + redraw_everything = YEA; + break; + case 'l': /* block delete */ + case ' ': + block_del(0); + line_dirty = 1; + break; + case 'u': + if(blockln >= 0) + block_del(1); + line_dirty = 1; + break; + case 'c': + if(blockln >= 0) + block_del(3); + line_dirty = 1; + break; + case 'y': + undelete_line(); + break; + case 'R': + raw_mode ^= 1; + line_dirty = 1; + break; + case 'I': + indent_mode ^= 1; + line_dirty = 1; + break; + case 'j': + if(blockln >= 0) + block_shift_left(); + else if(currline->len) { + int currpnt0 = currpnt; + currpnt = 0; + delete_char(); + currpnt = (currpnt0 <= currline->len) ? currpnt0 : + currpnt0 - 1; + if(my_ansimode) + currpnt = ansi2n(n2ansi(currpnt, currline), + currline); + } + line_dirty = 1; + break; + case 'k': + if(blockln >= 0) + block_shift_right(); + else { + int currpnt0 = currpnt; + + currpnt = 0; + insert_char(' '); + currpnt = currpnt0; + } + line_dirty = 1; + break; + case 'f': + while(currpnt < currline->len && + isalnum(currline->data[++currpnt])); + while(currpnt < currline->len && + isspace(currline->data[++currpnt])); + line_dirty = 1; + break; + case 'b': + while(currpnt && isalnum(currline->data[--currpnt])); + while(currpnt && isspace(currline->data[--currpnt])); + line_dirty = 1; + break; + case 'd': + while(currpnt < currline->len) { + delete_char(); + if(!isalnum(currline->data[currpnt])) + break; + } + while(currpnt < currline->len) { + delete_char(); + if(!isspace(currline->data[currpnt])) + break; + } + line_dirty = 1; + break; + default: + line_dirty = 1; + } + break; + case Ctrl('_'): + if(strcmp(line, currline->data)) { + char buf[WRAPMARGIN]; + + strcpy(buf, currline->data); + strcpy(currline->data, line); + strcpy(line, buf); + currline->len = strlen(currline->data); + currpnt = 0; + line_dirty = 1; + } + break; + case Ctrl('S'): + search_str(0); + break; + case Ctrl('U'): + insert_char('\033'); + line_dirty = 1; + break; + case Ctrl('V'): /* Toggle ANSI color */ + my_ansimode ^= 1; + if(my_ansimode && blockln >= 0) + block_color(); + clear(); + redraw_everything = YEA; + line_dirty = 1; + break; + case Ctrl('I'): + do { + insert_char(' '); + } while(currpnt & 0x7); + line_dirty = 1; + break; + case '\r': + case '\n': + split(currline, currpnt); + line_dirty = 0; + break; + case Ctrl('G'): + { + unsigned int currstat0 = currstat; + setutmpmode(EDITEXP); + a_menu("�s�軲�U��", "etc/editexp", + (HAS_PERM(PERM_SYSOP) ? SYSOP : NOBODY)); + currstat = currstat0; + } + if(trans_buffer[0]) { + if((fp1 = fopen(trans_buffer, "r"))) { + int indent_mode0 = indent_mode; + + indent_mode = 0; + prevln = currln; + prevpnt = currpnt; + while(fgets(line, WRAPMARGIN + 2, fp1)) { + if(!strncmp(line,"�@��:",5) || + !strncmp(line,"���D:",5) || + !strncmp(line,"�ɶ�:",5)) + continue; + insert_string(line); + } + fclose(fp1); + indent_mode = indent_mode0; + while(curr_window_line >= b_lines) { + curr_window_line--; + top_of_win = top_of_win->next; + } + } + } + redraw_everything = YEA; + line_dirty = 1; + break; + case Ctrl('Z'): /* Help */ + more("etc/ve.hlp",YEA); + redraw_everything = YEA; + line_dirty = 1; + break; + case Ctrl('L'): + clear(); + redraw_everything = YEA; + line_dirty = 1; + break; + case KEY_LEFT: + if(currpnt) { + if(my_ansimode) + currpnt = n2ansi(currpnt, currline); + currpnt--; + if(my_ansimode) + currpnt = ansi2n(currpnt, currline); + line_dirty = 1; + } else if(currline->prev) { + curr_window_line--; + currln--; + currline = currline->prev; + currpnt = currline->len; + line_dirty = 0; + } + break; + case KEY_RIGHT: + if(currline->len != currpnt) { + if(my_ansimode) + currpnt = n2ansi(currpnt, currline); + currpnt++; + if(my_ansimode) + currpnt = ansi2n(currpnt, currline); + line_dirty = 1; + } else if(currline->next) { + currpnt = 0; + curr_window_line++; + currln++; + currline = currline->next; + line_dirty = 0; + } + break; + case KEY_UP: + case Ctrl('P'): + if(currline->prev) { + if(my_ansimode) + ch = n2ansi(currpnt,currline); + curr_window_line--; + currln--; + currline = currline->prev; + if(my_ansimode) + currpnt = ansi2n(ch , currline); + else + currpnt = (currline->len > lastindent) ? lastindent : + currline->len; + line_dirty = 0; + } + break; + case KEY_DOWN: + case Ctrl('N'): + if(currline->next) { + if(my_ansimode) + ch = n2ansi(currpnt,currline); + currline = currline->next; + curr_window_line++; + currln++; + if(my_ansimode) + currpnt = ansi2n(ch , currline); + else + currpnt = (currline->len > lastindent) ? lastindent : + currline->len; + line_dirty = 0; + } + break; + case Ctrl('B'): + case KEY_PGUP: + redraw_everything = currln; + top_of_win = back_line(top_of_win, 22); + currln = redraw_everything; + currline = back_line(currline, 22); + curr_window_line = getlineno(); + if(currpnt > currline->len) + currpnt = currline->len; + redraw_everything = YEA; + line_dirty = 0; + break; + case KEY_PGDN: + case Ctrl('F'): + redraw_everything = currln; + top_of_win = forward_line(top_of_win, 22); + currln = redraw_everything; + currline = forward_line(currline, 22); + curr_window_line = getlineno(); + if(currpnt > currline->len) + currpnt = currline->len; + redraw_everything = YEA; + line_dirty = 0; + break; + case KEY_END: + case Ctrl('E'): + currpnt = currline->len; + line_dirty = 1; + break; + case Ctrl(']'): /* start of file */ + prevln = currln; + prevpnt = currpnt; + currline = top_of_win = firstline; + currpnt = currln = curr_window_line = 0; + redraw_everything = YEA; + line_dirty = 0; + break; + case Ctrl('T'): /* tail of file */ + prevln = currln; + prevpnt = currpnt; + top_of_win = back_line(lastline, 23); + currline = lastline; + curr_window_line = getlineno(); + currln = totaln; + redraw_everything = YEA; + currpnt = 0; + line_dirty = 0; + break; + case KEY_HOME: + case Ctrl('A'): + currpnt = 0; + line_dirty = 1; + break; + case KEY_INS: /* Toggle insert/overwrite */ + case Ctrl('O'): + if(blockln >= 0 && insert_character) { + char ans[4]; + + getdata(b_lines - 1, 0, + "�϶��L�եk�����J�r��(�w�]���ťզr��)", + ans, 4, LCECHO); + insert_c = (*ans) ? *ans : ' '; + } + insert_character ^= 1; + line_dirty = 1; + break; + case Ctrl('H'): + case '\177': /* backspace */ + line_dirty = 1; + if(my_ansimode) { + my_ansimode = 0; + clear(); + redraw_everything = YEA; + } else { + if(currpnt == 0) { + textline_t *p; + + if(!currline->prev) + break; + line_dirty = 0; + curr_window_line--; + currln--; + currline = currline->prev; + currpnt = currline->len; + redraw_everything = YEA; + if(*killsp(currline->next->data) == '\0') { + delete_line(currline->next); + break; + } + p = currline; + while(!join(p)) { + p = p->next; + if(p == NULL) { + indigestion(2); + abort_bbs(0); + } + } + break; + } + currpnt--; + delete_char(); + } + break; + case Ctrl('D'): + case KEY_DEL: /* delete current character */ + line_dirty = 1; + if(currline->len == currpnt) { + textline_t *p = currline; + + while(!join(p)) { + p = p->next; + if(p == NULL) { + indigestion(2); + abort_bbs(0); + } + } + line_dirty = 0; + redraw_everything = YEA; + } else { + delete_char(); + if(my_ansimode) + currpnt = ansi2n(n2ansi(currpnt, currline), currline); + } + break; + case Ctrl('Y'): /* delete current line */ + currline->len = currpnt = 0; + case Ctrl('K'): /* delete to end of line */ + if(currline->len == 0) { + textline_t *p = currline->next; + if(!p) { + p = currline->prev; + if(!p) + break; + if(curr_window_line > 0) { + curr_window_line--; + currln--; + } + } + if(currline == top_of_win) + top_of_win = p; + delete_line(currline); + currline = p; + redraw_everything = YEA; + line_dirty = 0; + break; + } + if(currline->len == currpnt) { + textline_t *p = currline; + + while(!join(p)) { + p = p->next; + if(p == NULL) { + indigestion(2); + abort_bbs(0); + } + } + redraw_everything = YEA; + line_dirty = 0; + break; + } + currline->len = currpnt; + currline->data[currpnt] = '\0'; + line_dirty = 1; + break; + } + if(currln < 0) + currln = 0; + if(curr_window_line < 0) { + curr_window_line = 0; + if(!top_of_win->prev) + indigestion(6); + else { + top_of_win = top_of_win->prev; + rscroll(); + } + } + if(curr_window_line == b_lines) { + curr_window_line = t_lines - 2; + if(!top_of_win->next) + indigestion(7); + else { + top_of_win = top_of_win->next; + move(b_lines, 0); + clrtoeol(); + scroll(); + } + } + } + edit_margin = currpnt < SCR_WIDTH - 1 ? 0 : currpnt / 72 * 72; + + if(!redraw_everything) { + if(edit_margin != last_margin) { + last_margin = edit_margin; + redraw_everything = YEA; + } else { + move(curr_window_line, 0); + clrtoeol(); + if(my_ansimode) + outs(currline->data); + else + edit_outs(&currline->data[edit_margin]); + edit_msg(); + } + } + } +} diff --git a/mbbsd/friend.c b/mbbsd/friend.c new file mode 100644 index 00000000..3d2167ae --- /dev/null +++ b/mbbsd/friend.c @@ -0,0 +1,509 @@ +/* $Id: friend.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/file.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +extern char currboard[]; /* name of currently selected board */ +extern char *fn_overrides; +extern userinfo_t *currutmp; +extern char *fn_reject; +extern int usernum; +extern char *str_space; +extern char *msg_uid; + +/* ------------------------------------- */ +/* �S�O�W�� */ +/* ------------------------------------- */ + +/* Ptt ��L�S�O�W�檺�ɦW */ +static char special_list[] = "list.0"; +static char special_des[] = "ldes.0"; + +/* �S�O�W�檺�W�� */ +static unsigned int friend_max[8] = { + MAX_FRIEND, + MAX_REJECT, + MAX_LOGIN_INFO, + MAX_POST_INFO, + MAX_NAMELIST, + MAX_NAMELIST, + MAX_NAMELIST, + MAX_NAMELIST +}; +/* ���M�n���a�H�W�泣�O * 2 ���O�@���̦hload��shm�u�128 */ + +/* Ptt �U�دS�O�W�檺�ɦW */ +char *friend_file[8] = { + FN_OVERRIDES, + FN_REJECT, + "alohaed", + "postlist", + "", + FN_CANVOTE, + FN_WATER, + FN_VISABLE +}; + +/* Ptt �U�دS�O�W�檺�ɭz */ +static char *friend_desc[8] = { + "�ͽ˴y�z�G", + "�c�δc���G", + "", + "", + "�y�z�@�U�G", + "�벼�̴y�z�G", + "�c�δc���G", + "�ݪO�n�ʹy�z" +}; + +/* Ptt �U�دS�O�W�檺����ԭz */ +static char *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��" +}; + +static 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]); +} + +static int friend_count(char *fname) { + FILE *fp; + int count = 0; + char buf[200]; + +#if 0 + if ((fp = fopen(fname, "r"))) + while (fgets(buf, 200, fp)) + count++; +#endif + +/*rocker.011018: �ѰO���ɤF... */ + if ((fp = fopen(fname, "r"))) + { + while (fgets(buf, 200, fp)) count++; + fclose (fp); + } + + return count; +} + +void friend_add(char *uident, int type) { + char fpath[80]; + + setfriendfile(fpath, type); + if (friend_count(fpath) > friend_max[type]) + return; + + if ((uident[0] > ' ') && !belong(fpath, uident)) + { + FILE *fp; + char buf[40] = ""; + char t_uident[IDLEN + 1]; + + /* Thor: avoid uident run away when get data */ + strcpy(t_uident, uident); + + if (type != FRIEND_ALOHA && type != FRIEND_POST) + getdata(2, 0, friend_desc[type], buf, 40, DOECHO); + + if ((fp = fopen(fpath, "a"))) + { + flock(fileno(fp), LOCK_EX); + fprintf(fp, "%-13s%s\n", t_uident, buf); + flock(fileno(fp), LOCK_UN); + fclose(fp); + } + } +} + +static void friend_special() { + char genbuf[70], i, fname[70]; + + friend_file[FRIEND_SPECIAL] = special_list; + for (i = 0; i <= 9; i++) + { + sprintf(genbuf, " (\033[36m%d\033[m) .. ", i); + special_des[5] = i + '0'; + setuserfile(fname, special_des); + if (dashf(fname)) + { + /* no NULL check?? */ + FILE *fp = fopen(fname, "r"); + + fgets(genbuf + 15, 40, fp); + genbuf[47] = 0; + } + 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; + + setfriendfile(fpath, type); + + do + { + move(2, 0); + clrtobot(); + outs("�n�ޤJ���@�ӦW��?\n"); + for (i = 0, j = 0; i <= 7; i++) + { + if (i == type) + continue; + j++; + if (i <= 4) + sprintf(buf, " (%d) %-s\n", j, friend_list[(int) i]); + else + sprintf(buf, " (%d) %s ���� %s\n", j, currboard, + friend_list[(int) i]); + outs(buf); + } + outs(" (S) ��ܨ�L�ݪO���S�O�W��"); + getdata(11, 0, "�п�� �� ����[Enter] ���:", buf, 3, LCECHO); + if (!buf[0]) + return; + if (buf[0] == 's') + Select(); + } + while (buf[0] < '1' || buf[0] > '9'); + + j = buf[0] - '1'; + if (j >= type) + j++; + if (j == FRIEND_SPECIAL) + friend_special(); + + setfriendfile(sfile, j); + + fp = fopen(sfile, "r"); + while (fgets(buf, 80, fp) && count <= friend_max[type]) + { + char the_id[15]; + + sscanf(buf, "%s", the_id); + if (!belong(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); +} + +void friend_delete(char *uident, int type) { + FILE *fp, *nfp; + char fn[80], fnnew[80]; + char genbuf[200]; + + setfriendfile(fn, type); + + sprintf(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); + fclose(fp); + fclose(nfp); + Rename(fnnew, fn); + } +} + +static void friend_editdesc(char *uident, int type) { + FILE *fp, *nfp; + char fnnew[200], genbuf[200], fn[200]; + setfriendfile(fn, type); + sprintf(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, "�ק�y�z�G", buf, 40, DOECHO); + fprintf(nfp, "%-13s%s\n", uident, buf); + } + } + fclose(fp); + fclose(nfp); + Rename(fnnew, fn); + } +} + +void friend_load() { + FILE *fp; + int myfriends[MAX_FRIEND]; + int myrejects[MAX_REJECT]; + int friendcount, rejectedcount; + char genbuf[200]; + + memset(myfriends, 0, sizeof(myfriends)); + friendcount = 0; + setuserfile(genbuf, fn_overrides); + if ((fp = fopen(genbuf, "r"))) + { + int unum; + + while (fgets(genbuf, STRLEN, fp) && friendcount < MAX_FRIEND - 1) + if (strtok(genbuf, str_space)) + if ((unum = searchuser(genbuf))) + myfriends[friendcount++] = unum; + fclose(fp); + } + memcpy(currutmp->friend, myfriends, sizeof(myfriends)); + + memset(myrejects, 0, sizeof(myrejects)); + rejectedcount = 0; + setuserfile(genbuf, fn_reject); + if ((fp = fopen(genbuf, "r"))) + { + int unum; + + while (fgets(genbuf, STRLEN, fp) && rejectedcount < MAX_REJECT - 1) + if (strtok(genbuf, str_space)) + if ((unum = searchuser(genbuf))) + myrejects[rejectedcount++] = unum; + fclose(fp); + } + memcpy(currutmp->reject, myrejects, sizeof(myrejects)); + if(currutmp->friendtotal) logout_friend_online(); + login_friend_online(); +} + +extern userec_t cuser; + +static void friend_water(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, "%s", userid); + if((tuid = searchuser(userid)) && tuid != usernum && + (uentp = (userinfo_t *) search_ulist(tuid)) && + isvisible_uid(tuid)) + my_write(uentp->pid, message, uentp->userid, 1); + } + fclose(fp); +} + +void friend_edit(int type) { + char fpath[80], line[80], uident[20]; + 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, "/bin/cp %s %s.old", fpath, fpath); + system(genbuf); + } + } + + dirty = 0; + while (1) + { + stand_title(friend_list[type]); + move(0, 40); + sprintf(line, "(�W��W��:%d�ӤH)", friend_max[type]); + outs(line); + count = 0; + CreateNameList(); + + if ((fp = fopen(fpath, "r"))) + { + move(3, 0); + column = 0; + while (fgets(genbuf, STRLEN, fp)) + { + if (genbuf[0] <= ' ') + continue; + strtok(genbuf, str_space); + 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)�����H[Q]" : + "(A)�W�[ (P)�ޤJ��L�W�� (Q)�����H[Q]"), + uident, 3, LCECHO); + if (*uident == 'a') + { + move(1, 0); + usercomplete(msg_uid, uident); + if (uident[0] && searchuser(uident) && !InNameList(uident)) + { + friend_add(uident, type); + dirty = 1; + } + } + else if (*uident == 'p') + { + friend_append(type, count); + dirty = 1; + } + else if (*uident == 'e' && count) + { + move(1, 0); + namecomplete(msg_uid, uident); + if (uident[0] && InNameList(uident)) + { + friend_editdesc(uident, type); + } + } + else if (*uident == 'd' && count) + { + move(1, 0); + namecomplete(msg_uid, uident); + if (uident[0] && InNameList(uident)) + { + friend_delete(uident, type); + dirty = 1; + } + } + else if (*uident == 'l' && count) + more(fpath, YEA); + else if (*uident == 'k' && count) + { + getdata(2, 0, "����W��N�|�Q�R��,�z�T�w�� (a/N)?", uident, 3, + LCECHO); + if (*uident == 'a') + unlink(fpath); + dirty = 1; + } + else if (*uident == 'w' && count) + { + if (!getdata(0, 0, "�s����y:", uident, 60, DOECHO)) + continue; + if (getdata(0, 0, "�T�w��X�s����y? [Y]", line, 4, LCECHO) && + *line == 'n') + continue; + friend_water(uident, type); + } + else + break; + } + if (dirty) + { + move(2, 0); + outs("��s��Ƥ�..�еy��....."); + refresh(); + if (type == FRIEND_ALOHA || type == FRIEND_POST) + { + sprintf(genbuf, "%s.old", fpath); + if ((fp = fopen(genbuf, "r"))) + { + while (fgets(line, 80, fp)) + { + sscanf(line, "%s", uident); + sethomefile(genbuf, uident, + type == FRIEND_ALOHA ? "aloha" : "postnotify"); + del_distinct(genbuf, cuser.userid); + } + fclose(fp); + } + sprintf(genbuf, "%s", fpath); + if ((fp = fopen(genbuf, "r"))) + { + while (fgets(line, 80, fp)) + { + sscanf(line, "%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"))) + { + fprintf(fp, "%s", genbuf); + fclose(fp); + } + } + friend_load(); + } +} + +int t_override() { + friend_edit(FRIEND_OVERRIDE); + return 0; +} + +int t_reject() { + friend_edit(FRIEND_REJECT); + return 0; +} diff --git a/mbbsd/gamble.c b/mbbsd/gamble.c new file mode 100644 index 00000000..23867450 --- /dev/null +++ b/mbbsd/gamble.c @@ -0,0 +1,361 @@ +/* $Id: gamble.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <time.h> +#include <string.h> +#include <sys/types.h> +#include <stdlib.h> +#include <unistd.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" +extern int usernum; + +#ifndef _BBS_UTIL_C_ +extern userec_t cuser; +extern int b_lines; + +#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 char betname[MAX_ITEM][MAX_ITEM_LEN]; +static int currbid; + +int post_msg(char* bname, char* title, char *msg, char* author) +{ + FILE *fp; + int bid; + fileheader_t fhdr; + time_t now = time(0); + char genbuf[256]; + + /* �b bname ���o���s�峹 */ + sprintf(genbuf, "boards/%s", bname); + stampfile(genbuf, &fhdr); + fp = fopen(genbuf,"w"); + + if(!fp) + return -1; + + fprintf(fp, "�@��: %s �ݪO: %s\n���D: %s \n",author,bname,title); + fprintf(fp, "�ɶ�: %s\n", ctime(&now)); + + /* �峹�����e */ + fprintf(fp, "%s", msg); + fclose(fp); + + /* �N�ɮץ[�J�C�� */ + strcpy(fhdr.title, title); + strcpy(fhdr.owner, author); + setbdir(genbuf,bname); + if(append_record(genbuf, &fhdr, sizeof(fhdr))!=-1) + if((bid = getbnum(bname)) > 0) + setbtotal(bid); + return 0; +} + +int post_file(char* bname, char* title, char *filename, 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); + fread(msg,1,size,fp); + size= post_msg(bname, title, msg, author); + fclose(fp); + free(msg); + return size; +} + + +static int load_ticket_record(char *direct, int ticket[]) +{ + char buf[256]; + int i, total=0; + FILE *fp; + sprintf(buf,"%s/"FN_TICKET_RECORD,direct); + if(!(fp=fopen(buf,"r"))) return 0; + for(i=0;i<MAX_ITEM && fscanf(fp, "%9d ",&ticket[i]); i++) + total=total+ticket[i]; + fclose(fp); + return total; +} + +static int show_ticket_data(char *direct, int *price, 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]; + + clear(); + if (bh) + { + sprintf(genbuf,"%s ��L", bh->brdname); + showtitle(genbuf, BBSNAME); + } + else + showtitle("Ptt��L", BBSNAME); + move(2, 0); + sprintf(genbuf, "%s/"FN_TICKET_ITEMS, direct); + if(!(fp = fopen(genbuf,"r"))) + { + prints("\n�ثe�èS���|���L\n"); + sprintf(genbuf, "%s/"FN_TICKET_OUTCOME, direct); + if(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++) + strtok(betname[count],"\r\n"); + fclose(fp); + + prints("\033[32m���W:\033[m 1.�i�ʶR�H�U���P�������m���C�C�i�n�� \033[32m%d\033[m ���C\n" + " 2.%s\n" + " 3.�}���ɥu���@�رm������, ���ʶR�ӱm����, �h�i���ʶR���i�Ƨ���" + "�`����C\n" + " 4.�C�������Ѩt�Ω�� 5% ���|��%s�C\n\n" + "\033[32m%s:\033[m", *price, + bh?"����L�Ѫ��D�t�d�|��åB�M�w�}���ɶ����G, ��������, �@��A��C": + "�t�ΨC�� 2:00 11:00 16:00 21:00 �}���C", + bh?", �䤤 2% �����}�����D":"", + bh?"���D�ۭq�W�h�λ���":"�e�X���}�����G"); + + + sprintf(genbuf, "%s/"FN_TICKET, direct); + if(!dashf(genbuf)) + { + sprintf(genbuf, "%s/"FN_TICKET_END, direct); + end=1; + } + show_file(genbuf, 8, -1, NO_RELOAD); + move(15,0); + prints("\033[1;32m�ثe�U�`���p:\033[m\n"); + + total=load_ticket_record(direct, ticket); + + prints("\033[33m"); + for(i = 0 ; i<count; i++) + { + prints("%d.%-8s: %-7d", i+1, betname[i], ticket[i]); + if(i==3) prints("\n"); + } + prints("\033[m\n\033[42m �U�`�`���B:\033[31m %d �� \033[m",total*(*price)); + if(end) + { + prints("\n��L�w�g����U�`\n"); + return -count; + } + return count; +} + +static void append_ticket_record(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]; + sprintf(genbuf, "%s/"FN_TICKET_USER, direct); + + if((fp = fopen(genbuf,"a"))) { + fprintf(fp, "%s %d %d\n", cuser.userid, ch, n); + fclose(fp); + } + load_ticket_record(direct, ticket); + ticket[ch] += n; + sprintf(genbuf, "%s/" FN_TICKET_RECORD, direct); + if((fp = fopen(genbuf,"w"))) { + for(i=0; i<count; i++) + fprintf(fp,"%d ", ticket[i]); + fclose(fp); + } +} + +#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 +int ticket(int bid) +{ + int ch, n, price, count, end=0; + char path[128],fn_ticket[128]; + boardheader_t *bh=NULL; + + 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(path, &price, bh); + if(count<=0) + { + pressanykey(); + break; + } + move(20, 0); + reload_money(); + prints("\033[44m��: %-10d \033[m\n\033[1m�п�ܭn�ʶR������(1~%d)" + "[Q:���}]\033[m:", cuser.money,count); + ch = igetch(); + /*-- + Tim011127 + ���F����CS���D ���O�o���٤��৹���ѨM�o���D, + �Yuser�q�L�ˬd�U�h, ��n���D�}��, �٬O�|�y��user���o������ + �ܦ��i��]��U����L�������h, �]�ܦ��i��Q���D�s�}��L�ɬ~�� + ���L�o��ܤ֥i�H���쪺�O, ���h�u�|���@����ƬO���� + --*/ + if(bid && !dashf(fn_ticket)) + { + move(b_lines-1,0); + prints("�z!! �@����...���D�w�g����U�`�F ������P"); + pressanykey(); + break; + } + + if(ch=='q' || ch == 'Q') + break; + ch-='1'; + if(end || ch >= count || ch < 0) + continue; + n=0; + ch_buyitem(price, "etc/buyticket", &n); + if(n > 0) + append_ticket_record(path,ch,n,count); + } + unlockutmpmode(); + return 0; +} + +int openticket(int bid) { + char path[128],buf[256],outcome[128]; + int i, money=0, count, bet, price, total = 0, ticket[8]={0,0,0,0,0,0,0,0}; + boardheader_t *bh=getbcache(bid); + time_t now = time(NULL); + FILE *fp, *fp1; + + setbpath(path, bh->brdname); + count=-show_ticket_data(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, "\033[1m��ܤ��������X(0:����)\033[m:", buf, 3, LCECHO); + bet=atoi(buf); + move(0,0); + clrtoeol(); + } while(bet<0 || bet>count); + if(bet==0) + {unlockutmpmode(); return 0;} + getdata(21, 0, "\033[1m�A���T�{���������X\033[m:", buf, 3, LCECHO); + }while(bet!=atoi(buf)); + + bet -= 1; //�ন�x�}��index + + total=load_ticket_record(path, ticket); + setbfile(buf,bh->brdname,FN_TICKET_END); + if(!(fp1 = fopen(buf,"r"))) + { + unlockutmpmode(); + return 0; + } + // �٨S�}���������� �u�nmv�@���N�n + 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; + setbfile(outcome,bh->brdname,FN_TICKET_OUTCOME); + if((fp = fopen(outcome, "w"))) + { + fprintf(fp,"��L����\n"); + while(fgets(buf,256,fp1)) + { + buf[255]=0; + fprintf(fp,"%s",buf); + } + fprintf(fp,"�U�`���p\n"); + + fprintf(fp, "\033[33m"); + 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, "\033[m\n"); + + 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 �T�� \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", + Cdatelite(&now), betname[bet], total*price, money, + total? (float)ticket[bet] / total:0); + + fclose(fp); + } + fclose(fp1); + + setbfile(buf, bh->brdname, FN_TICKET_END); + unlink(buf); +/* + if(fork()) + { + more(outcome,YEA); + unlockutmpmode(); + return 0; + } +*/ + sprintf(buf, "[���i] %s ��L�}��", bh->brdname); + post_file(bh->brdname, buf, outcome, "[�䯫]"); + post_file("Record", buf+7, outcome, "[�������l]"); + /* + �H�U�O�����ʧ@ + */ + setbfile(buf, bh->brdname, FN_TICKET_USER); + if (ticket[bet] && (fp = fopen(buf, "r"))) + { + int mybet, uid; + char userid[IDLEN]; + + while (fscanf(fp, "%s %d %d\n", userid, &mybet, &i) != EOF) + { + if (mybet == bet) + { + printf("���� %-15s�R�F%9d �i %s, ��o %d �T��\n" + ,userid, i, betname[mybet], money * i); + if((uid=getuser(userid))==0) continue; + deumoney(uid, money * i); + sprintf(buf, "%s ������! $ %d", bh->brdname, money * i); + mail_id(userid, buf, outcome, "Ptt���"); + } + } + } + setbfile(buf, bh->brdname, FN_TICKET_RECORD); + unlink(buf); + setbfile(buf, bh->brdname, FN_TICKET_USER); + unlink(buf); + return 0; +} + +int ticket_main() { + ticket(0); + return 0; +} +#endif diff --git a/mbbsd/gomo.c b/mbbsd/gomo.c new file mode 100644 index 00000000..06062ce4 --- /dev/null +++ b/mbbsd/gomo.c @@ -0,0 +1,417 @@ +/* $Id: gomo.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "gomo.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern int usernum; +extern userinfo_t *currutmp; + +char ku[BRDSIZ][BRDSIZ]; +static char *chess[] = { "��", "��" }; +static int tick, lastcount, mylasttick, hislasttick; + +unsigned char *pat, *adv; + +typedef struct { + char x; + char y; +} Horder_t; + +static Horder_t *v, pool[225]; + +static void HO_init() { + memset(pool, 0, sizeof(pool)); + v = pool; + pat = pat_gomoku; + adv = adv_gomoku; + memset(ku, 0, sizeof(ku)); +} + +static void HO_add(Horder_t *mv) { + *v++ = *mv; +} + +static void HO_undo(Horder_t *mv) { + char *str = "�z�s�{�u�q�t�|�r�}"; + int n1, n2, loc; + + *mv = *(--v); + ku[(int)mv->x][(int)mv->y] = BBLANK; + BGOTO(mv->x, mv->y); + n1 = (mv->x == 0) ? 0 : (mv->x == 14) ? 2 : 1; + n2 = (mv->y == 14)? 0 : (mv->y == 0) ? 2 : 1; + loc= 2 * ( n2 * 3 + n1); + prints("%.2s", str + loc); +} + +extern userec_t cuser; + +static void HO_log(char *user) { + int i; + FILE *log; + char buf[80]; + char buf1[80]; + char title[80]; + Horder_t *ptr = pool; + extern screenline_t *big_picture; + fileheader_t mymail; + + sprintf(buf, "home/%c/%s/F.%d", cuser.userid[0], cuser.userid, + rand() & 65535); + log = fopen(buf, "w"); + + for(i = 1; i < 17; i++) + fprintf(log, "%.*s\n", big_picture[i].len, big_picture[i].data); + + i = 0; + do { + fprintf(log, "[%2d]%s ==> %c%d%c", i + 1, chess[i % 2], + 'A' + ptr->x, ptr->y + 1, (i % 2) ? '\n' : '\t'); + i++; + } while( ++ptr < v); + fclose(log); + + sethomepath(buf1, cuser.userid); + stampfile(buf1, &mymail); + + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, "[��.��.��]"); + sprintf(mymail.title, "\033[37;41m����\033[m %s VS %s", + cuser.userid, user); + sethomedir(title, cuser.userid); + Rename(buf, buf1); + append_record(title, &mymail, sizeof(mymail)); + + unlink(buf); +} + +static int countgomo() { + Horder_t *ptr; + int i; + + ptr = pool; + i = 0; + do { + i++; + } while(++ptr < v); + return i; +} + +static int chkmv(Horder_t *mv, int color, int limit) { + char *xtype[] = {"\033[1;31m���T\033[m", "\033[1;31m���T\033[m", + "\033[1;31m���|\033[m", "\033[1;31m���|\033[m", + "\033[1;31m���|\033[m", "\033[1;31m�|�T\033[m", + "\033[1;31m���T\033[m", "\033[1;31m���|\033[m", + "\033[1;31m���|\033[m", "\033[1;31m�s��\033[m", + "\033[1;31m�s��\033[m"}; + int rule = getstyle(mv->x, mv->y, color, limit); + if(rule > 1 && rule < 13) { + move(15, 40); + outs(xtype[rule - 2]); + bell(); + } + return chkwin(rule, limit); +} + +static int gomo_key(int fd, int ch, Horder_t *mv) { + if( ch >= 'a' && ch <= 'o') { + char pbuf[4], vx, vy; + + *pbuf = ch; + if(fd) + add_io(0, 0); + oldgetdata(17, 0, "�������w��m :", pbuf, 4, DOECHO); + if(fd) + add_io(fd, 0); + vx = pbuf[0] - 'a'; + vy = atoi(pbuf + 1) - 1; + if(vx >= 0 && vx < 15 && vy >= 0 && vy < 15 && + ku[(int)vx][(int)vy] == BBLANK) { + mv->x = vx; + mv->y = vy; + return 1; + } + } else { + switch(ch) { + case KEY_RIGHT: + mv->x = (mv->x == BRDSIZ - 1) ? mv->x : mv->x + 1; + break; + case KEY_LEFT: + mv->x = (mv->x == 0 ) ? 0 : mv->x - 1; + break; + case KEY_UP: + mv->y = (mv->y == BRDSIZ - 1) ? mv->y : mv->y + 1; + break; + case KEY_DOWN: + mv->y = (mv->y == 0 ) ? 0 : mv->y - 1; + break; + case ' ': + case '\r': + if(ku[(int)mv->x][(int)mv->y] == BBLANK) + return 1; + } + } + return 0; +} + +extern userec_t xuser; + +static int reload_gomo() { + passwd_query(usernum, &xuser); + cuser.five_win = xuser.five_win; + cuser.five_lose = xuser.five_lose; + cuser.five_tie = xuser.five_tie; + return 0; +} + +int gomoku(int fd) { + Horder_t mv; + int me, he, win, ch; + int hewantpass, iwantpass; + userinfo_t *my = currutmp; + + HO_init(); + me = !(my->turn) + 1; + he = my->turn + 1; + win = 1; + tick=time(0) + MAX_TIME; + lastcount = MAX_TIME; + setutmpmode(M_FIVE); + clear(); + + prints("\033[1;46m ���l�ѹ�� \033[45m%30s VS %-30s\033[m", + cuser.userid, my->mateid); + show_file("etc/@five", 1, -1, ONLY_COLOR); + move(11, 40); + prints("�ڬO %s", me == BBLACK ? "���� ��, ���T��" : "��� ��"); + move(16, 40); + prints("\033[1;33m%s", cuser.userid); + move(17, 40); + prints("\033[1;33m%s", my->mateid); + + reload_gomo(); + move(16, 60); + prints("\033[1;31m%d\033[37m�� \033[34m%d\033[37m�� \033[36m%d\033[37m�M" + "\033[m", cuser.five_win, cuser.five_lose, cuser.five_tie); + + getuser(my->mateid); + move(17, 60); + prints("\033[1;31m%d\033[37m�� \033[34m%d\033[37m�� \033[36m%d\033[37m" + "�M\033[m", xuser.five_win, xuser.five_lose, xuser.five_tie); + + cuser.five_lose++; + /* �@�i�ӥ��[�@���ѳ�, Ĺ�F��A���^�h, �קK�ֿ�F�c�N�_�u */ + passwd_update(usernum, &cuser); + + add_io(fd, 0); + + hewantpass = iwantpass = 0; + mv.x = mv.y = 7; + move(18, 40); + prints("%s�ɶ��ٳ�%d:%02d\n", my->turn ? "�A��" : "���", + MAX_TIME / 60, MAX_TIME % 60); + for(;;) { + move(13, 40); + outs(my->turn ? "����ۤv�U�F!": "���ݹ��U�l.."); + if(lastcount != tick-time(0)) { + lastcount = tick-time(0); + move(18, 40); + prints("%s�ɶ��ٳ�%d:%02d\n", my->turn ? "�A��" : "���", + lastcount / 60, lastcount % 60); + if(lastcount <= 0 && my->turn) { + move(19, 40); + outs("�ɶ��w��, �A��F"); + my->five_lose++; + send(fd, '\0', 1, 0); + break; + } + if(lastcount <= -5 && !my->turn) { + move(19, 40); + outs("���Ӥ[�S�U, �AĹ�F!"); + win = 1; + cuser.five_lose--; + cuser.five_win++; + my->five_win++; + passwd_update(usernum, &cuser); + mv.x = mv.y = -2; + send(fd, &mv, sizeof(Horder_t), 0); + mv = *(v - 1); + break; + } + } + move(14, 40); + if(hewantpass) { + outs("\033[1;32m�M�ѭn�D!\033[m"); + bell(); + } else + clrtoeol(); + BGOTOCUR(mv.x, mv.y); + ch = igetkey(); + if(ch != I_OTHERDATA) + iwantpass = 0; + if(ch == 'q') { + if(countgomo() < 10) { + cuser.five_lose--; + passwd_update(usernum, &cuser); + } + send(fd, '\0', 1, 0); + break; + } else if(ch == 'u' && !my->turn && v > pool) { + mv.x = mv.y = -1; + ch = send(fd, &mv, sizeof(Horder_t), 0); + if(ch == sizeof(Horder_t)) { + HO_undo(&mv); + tick = mylasttick; + my->turn = 1; + continue; + } else + break; + } + if(ch == 'p') { + if(my->turn ) { + if(iwantpass == 0) { + iwantpass = 1; + mv.x = mv.y = -2; + send(fd, &mv, sizeof(Horder_t), 0); + mv = *(v - 1); + } + continue; + } else if(hewantpass) { + win = 0; + cuser.five_lose--; + cuser.five_tie++; + my->five_tie++; + passwd_update(usernum, &cuser); + mv.x=mv.y=-2; + send(fd, &mv, sizeof(Horder_t), 0); + mv = *(v - 1); + break; + } + } + + if(ch == I_OTHERDATA) { + ch = recv(fd, &mv, sizeof(Horder_t), 0); + if(ch != sizeof(Horder_t)) { + lastcount=tick-time(0); + if(lastcount >=0) { + win = 1; + cuser.five_lose--; + if(countgomo() >=10) { + cuser.five_win++; + my->five_win++; + } + passwd_update(usernum, &cuser); + outmsg("���{��F!!"); + break; + } else { + win = 0; + outmsg("�A�W�L�ɶ����U�l, ��F!"); + my->five_lose++; + break; + } + } else if(mv.x == -2 && mv.y == -2) { + if(iwantpass == 1) { + win = 0; + cuser.five_lose--; + cuser.five_tie++; + my->five_tie++; + passwd_update(usernum, &cuser); + break; + } else { + hewantpass = 1; + mv = *(v - 1); + continue; + } + } + if(my->turn && mv.x == -1 && mv.y == -1) { + outmsg("��讬��"); + tick = hislasttick; + HO_undo(&mv); + my->turn = 0; + continue; + } + + if(!my->turn) { + win = chkmv(&mv, he, he == BBLACK); + HO_add(&mv); + hislasttick = tick; + tick = time(0) + MAX_TIME; + ku[(int)mv.x][(int)mv.y] = he; + bell(); + BGOTO(mv.x, mv.y); + outs(chess[he - 1]); + + if(win) { + outmsg(win == 1 ? "���Ĺ�F!" : "���T��"); + if(win != 1) { + cuser.five_lose--; + cuser.five_win++; + my->five_win++; + passwd_update(usernum, &cuser); + } else + my->five_lose++; + win = -win; + break; + } + my->turn = 1; + } + continue; + } + + if(my->turn) { + if(gomo_key(fd, ch, &mv)) + my->turn = 0; + else + continue; + + if(!my->turn) { + HO_add(&mv); + BGOTO(mv.x, mv.y); + outs(chess[me - 1]); + win = chkmv( &mv, me, me == BBLACK); + ku[(int)mv.x][(int)mv.y] = me; + mylasttick = tick; + tick = time(0) + MAX_TIME; /*�˼�*/ + lastcount = MAX_TIME; + if(send(fd, &mv, sizeof(Horder_t), 0) != sizeof(Horder_t)) + break; + if(win) { + outmsg(win == 1 ? "��Ĺ�o~~" : "�T���F" ); + if(win == 1) { + cuser.five_lose--; + cuser.five_win++; + my->five_win++; + passwd_update(usernum, &cuser); + } else + my->five_lose++; + break; + } + move(15, 40); + clrtoeol(); + } + } + } + add_io(0, 0); + close(fd); + + igetch(); + if(v > pool) { + char ans[4]; + + getdata(19 , 0, "�n�O�d���������ж�?(y/N)", ans, 4, LCECHO); + if(*ans == 'y') + HO_log(my->mateid); + } + return 0; +} diff --git a/mbbsd/gomo1.c b/mbbsd/gomo1.c new file mode 100644 index 00000000..953bad2d --- /dev/null +++ b/mbbsd/gomo1.c @@ -0,0 +1,136 @@ +/* $Id: gomo1.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "proto.h" + +#define QCAST int (*)(const void *, const void *) + +#define BBLANK (0) /* �ť� */ +#define BBLACK (1) /* �¤l, ���� */ +#define BWHITE (2) /* �դl, ��� */ +#ifndef BRDSIZ +#define BRDSIZ (15) /* �ѽL����j�p */ +#endif + +extern char ku[BRDSIZ][BRDSIZ]; + +/* pattern and advance map */ +extern unsigned char *pat, *adv; + +static int intrevcmp(const void *a, const void *b) { + return (*(int *)b - *(int *)a); +} + +/* x,y: 0..BRDSIZ-1 ; color: CBLACK,CWHITE ; dx,dy: -1,0,+1 */ +static int gomo_getindex(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 <<= 1) { + 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; +} + +int chkwin(int style, int limit) { + if(style == 0x0c) + return 1 /* style */; + else if(limit == 0) { + if(style == 0x0b) + return 1 /* style */; + return 0; + } + if((style < 0x0c) && (style > 0x07)) + return -1 /* -style */; + return 0; +} + +/* x,y: 0..BRDSIZ-1 ; color: CBLACK,CWHITE ; limit:1,0 ; dx,dy: 0,1 */ +static int dirchk(int x, int y, int color, int limit, int dx, int dy) { + int le, ri, loc, style; + + le = gomo_getindex(x, y, color, -dx, -dy); + ri = gomo_getindex(x, y, color, dx, dy); + + loc = (le > ri) ? (((le * (le + 1)) >> 1) + ri) : + (((ri * (ri + 1)) >> 1) + le); + + style = pat[loc]; + + if(limit == 0) + return (style & 0x0f); + + style >>= 4; + + if((style == 3) || (style == 2)) { + int i, n, tmp, nx, ny; + + n = adv[loc >> 1]; + + ((loc & 1) == 0) ? (n >>= 4) : (n &= 0x0f); + + 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(nx, ny, color, 0, dx, dy) == 0x06) && + (chkwin(getstyle(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 */ +int getstyle(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; + + for(i = 0; i < 4; i++) + dir[i] = dirchk(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; +} diff --git a/mbbsd/guess.c b/mbbsd/guess.c new file mode 100644 index 00000000..27a337f7 --- /dev/null +++ b/mbbsd/guess.c @@ -0,0 +1,364 @@ +/* $Id: guess.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern char *BBSName; +extern int usernum; +#define LOGPASS BBSHOME "/etc/winguess.log" + +static void show_table(char TABLE[], char ifcomputer) { + int i; + + move(0, 35); + prints("\033[1;44;33m �i �q�Ʀr �j \033[m"); + move(8, 1); + prints("\033[1;44;36m�� �e �� �v\033[m\n"); + prints("\033[1;33m=================\033[m\n"); + if(ifcomputer) { + prints("Ĺ�q��: 2 ��\n"); + prints("��q��: 0 ��\n"); + } else { + for(i = 1; i <= 6; i++) + prints("��%d��, %02d��\n",i,TABLE[i]); + } + prints("\033[33m=================\033[m"); +} + +extern userec_t cuser; + +static unsigned long int get_money(void) { + int money, i; + char data[20]; + + move(1, 0); + prints("�z�ثe��:%d Ptt$", cuser.money); + do { + getdata(2, 0, "�n��h��(5-10�Ϋ�q���}): ", data, 9, LCECHO); + money = strlen(data); + if(data[0] == 'q' || data[0] == 'Q') { + unlockutmpmode(); + return 0; + } + for(i = 0; i < money; i++) + if(data[i]<'0' || data[i]>'9') { + money = -1; + break; + } + if(money != -1){ + money = atol(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 Ptt$", cuser.money - money); + return money; +} + +static int check_data(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(int count) { + static char data[5]; + while(1) { + getdata(6, 0, "��J�|��Ʀr(������): ", data, 5, LCECHO); + if(check_data(data) == 1) + break; + } + return data; +} + +static int guess_play(char *data, 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 => \033[1;32m%dA %dB\033[m", 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]; + + sprintf(n1, "%04d",correct); + sprintf(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]; + + sprintf(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 = rand() % 10000; + } while(!legal(guess)); + } else + guess = n[rand() % j]; + k = result(correct, guess); + if(k == 40) { + move(total + 8, 25); + sprintf(data, "%04d", guess); + prints("%s => �q���F!!", data); + return 1; + } else { + move(total + 8, 25); + sprintf(data, "%04d", guess); + prints("%s => \033[1;32m%dA %dB\033[m", 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 = rand() % 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() { + unsigned long int money; + char computerwin = 0,youwin = 0; + int count = 0,c_count = 0; + char ifcomputer; + char answer[5]; + int *n = NULL; + char yournum[5]; + char *flag = NULL; + static 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); + prints("�������� �ܤ֭n 5 Ptt$"); + unlockutmpmode(); + pressanykey(); + return 1; + } + if((money = get_money()) == 0) + return 1; + vice(money,"�q�Ʀr"); + + Diff_Random(answer); + move(2, 0); + clrtoeol(); + prints("�z�U�` :%d Ptt$", money); + + getdata_str(4, 0, "�z�n�M�q�����ɶ�? <y/n>[y]:", &ifcomputer, 2, + LCECHO, "y"); + if(ifcomputer == 'y') { + ifcomputer = 1; + show_table(TABLE, 1); + } else { + ifcomputer = 0; + show_table(TABLE, 0); + } + if(ifcomputer) { + do { + getdata(5, 0, "�п�J�z�n���q���q���Ʀr: ", yournum, 5, LCECHO); + } while(!legal(atoi(yournum))); + move(8, 25); + prints("�q���q"); + flag = malloc(sizeof(char) * 10000); + n = malloc(sizeof(int) * 1500); + initcomputer(flag); + } + move(8, 55); + prints("�A�q"); + while(((!computerwin || !youwin) && count <10 && (ifcomputer)) || + (!ifcomputer && count < 10 && !youwin)) { + if(!computerwin && ifcomputer) { + ++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(count),answer,count)) + youwin=1; + } + } + move(17, 35); + if(ifcomputer) { + free(flag); + free(n); + if(count > c_count) { + prints("�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 %ld Ptt$\n", cuser.userid, money); + fclose(file); + } + unlockutmpmode(); + pressanykey(); + return 1; + } else if(count < c_count) { + prints("�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�� %ld Ptt$\n", cuser.userid, count, + c_count, money * 2); + fclose(file); + } + unlockutmpmode(); + pressanykey(); + return 1; + } 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) { + prints("�u�F�`, ���Q�A�Ȩ��F"); + if((file = fopen(LOGPASS,"a"))) { + fprintf(file, "id: %s, ��%d���q��, Ĺ�F %ld Ptt$\n", + cuser.userid, count, TABLE[count] * money); + fclose(file); + } + } else if(count > 5) { + prints("��, �Ӧh���~�q�X�ӤF"); + if((file = fopen(LOGPASS,"a"))) { + fprintf(file, "id: %s, ��%d���~�q��, �ߤF %ld Ptt$\n", + cuser.userid, count, money); + fclose(file); + } + } + else { + prints("�����q�X��, �٧A�����a"); + move(18,35); + clrtoeol(); + prints("�A���^�F%d Ptt$\n", money); + if((file = fopen(LOGPASS,"a"))) { + fprintf(file, "id: %s, ��%d���q��, ���^�F���� %ld Ptt$\n", + cuser.userid, count, money); + fclose(file); + } + } + unlockutmpmode(); + pressanykey(); + return 1; + } + move(17,35); + prints("�K�K �зǵ��O %s ", answer); + move(18,35); + prints("�U���A�ӧa"); + if((file = fopen(BBSHOME "/etc/loseguess.log","a"))) { + fprintf(file,"id: %s ��F %ld Ptt$\n",cuser.userid,money); + fclose(file); + } + return 1; +} diff --git a/mbbsd/indict.c b/mbbsd/indict.c new file mode 100644 index 00000000..407b5ae9 --- /dev/null +++ b/mbbsd/indict.c @@ -0,0 +1,184 @@ +/* $Id: indict.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +#define REFER "etc/dicts" + +extern userec_t cuser; +char dict[41],database[41]; + +static void addword(char word[]) { + char buf[150],temp[150],a[3]; + FILE *fp = fopen(database,"r+"); + + fgets(buf,130,fp); + fseek(fp,0,2); + if(HAVE_PERM(PERM_LOGINOK)) { + clear(); + move(4,0); + outs(" \033[31mĵ�i\033[m:�Y�W�N��g����ƱN\033[36m��id\033[m�B��\n"); + sprintf(temp, "\n��J�d�Q\n:\033[33m%s\033[m", buf); + outs(temp); + outs("\n�Ш̤W�C�d�ҿ�J�@����(����enter���)\n"); + getdata(10, 0, ":", buf, 65, DOECHO); + if(buf[0]) { + getdata(13, 0, "�T�w�s�W?(Y/n)", a, 2, LCECHO); + if(a[0] != 'n') + fprintf(fp, "%-65s[%s]\n", buf, cuser.userid); + } + } + fclose(fp); + clear(); +} + +static int choose_dict(void) { + int c; + FILE *fp; + char buf[10][21], data[10][21], cho[130]; + + move(12, 0); + clrtobot(); + outs(" " + "�� \033[45;33m�r��� �� �n�d���@���H\033[m ��"); + + if((fp = fopen(REFER, "r"))) { + for(c = 0; fscanf(fp, "%s %s", buf[c], data[c]) != EOF; c++ ) { + sprintf(cho,"\n " + "(\033[36m%d\033[m) %-20s�j�r��",c+1,buf[c]); + outs(cho); + } + + getdata(22, 14, " �� �п�ܡA[Enter]���}�G", cho, 3, LCECHO); + cho[0] -= '1'; + if(cho[1]) + cho[0] = (cho[0] + 1) * 10 + (cho[1] - '1'); + + if(cho[0] >= 0 && cho[0] < c) { + strcpy(dict, buf[(int)cho[0]]); + strcpy(database, data[(int)cho[0]]); + return 1; + } else + return 0; + } + return 0; +} + +static char *lower(char str[]) { + int c; + static char temp[200]; + + strcpy(temp,str); + for(c = 0; temp[c] !=0; c++) + if(temp[c] >= 'A' && temp[c] <= 'Z') + temp[c] += 'a' - 'A'; + return temp; +} + +int use_dict() { + FILE *fp; + char lang[150], word[80] = ""; + char j, f, buf[120], sys[] = "|\033[31me\033[m:�s�y�r��"; + int i = 0; + + setutmpmode(DICT); + if(!HAS_PERM(PERM_SYSOP)) + sys[0]=0; + + clear(); + + sprintf(buf,"\033[45m ��\033[1;44;33m" + " %-14s\033[3;45m �� ", dict); + strcpy(&buf[100],"\033[m\n"); + for(;;) { + move(0, 0); + sprintf(lang, " �п�J����r��(%s) �Ϋ��O(h,t,a)\n", dict); + outs(lang); + sprintf(lang, "[\033[32m<����r>\033[m|\033[32mh\033[m:help|\033[32m" + "t\033[m:�Ҧ����|\033[32ma\033[m:�s�W���%s]\n:", sys); + outs(lang); + getdata(2, 0, ":", word, 18, DOECHO); + outs("��Ʒj�M���еy��...."); + strcpy(word,lower(word)); + if(word[0] == 0) + return 0; + clear(); + move(4, 0); + outs(buf); + if(strlen(word) == 1) { + if(word[0] == 'a') { + clear(); + move(4,0); + outs(buf); + addword(word); + continue; + } else if(word[0] == 't') + word[0] = 0; + else if(word[0] == 'h') { + more("etc/dict.hlp",YEA); + clear(); + continue; + } else if(word[0]=='e') { + vedit(database,NA, NULL); + clear(); + continue; + } else { + outs("�r��ӵu,�п�J�h�@�I����r"); + continue; + } + } + + if((fp = fopen(database,"r"))) { + i = 0; + while(fgets(lang,150,fp) != NULL) { + if(lang[65] == '[') { + lang[65] = 0; + f = 1; + } else + f = 0; + if(strstr(lower(lang),word)) { + if(f == 1) + lang[65] = '['; + outs(lang); + i++; + if(!((i+1)%17)) { + move(23, 0); + outs("\033[45m " + "���N���~�� Q:���} " + "\033[m "); + j = igetch(); + if(j == 'q') + break; + else { + clear(); + move(4,0); + outs(buf); + } + } + } + } + } + fclose(fp); + if(i == 0) { + getdata(5, 0, "�S�o�Ӹ�ƭC,�s�W��?(y/N)", lang, 3, LCECHO); + if(lang[0] == 'y') { + clear(); + move(4,0); + outs(buf); + addword(word); + } + } + } +} + +int x_dict() { + if(choose_dict()) + use_dict(); + return 0; +} diff --git a/mbbsd/io.c b/mbbsd/io.c new file mode 100644 index 00000000..e3d03b9b --- /dev/null +++ b/mbbsd/io.c @@ -0,0 +1,611 @@ +/* $Id: io.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <time.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <signal.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "modes.h" +#include "common.h" +#include "proto.h" + +#if defined(linux) +#define OBUFSIZE 2048 +#define IBUFSIZE 128 +#else +#define OBUFSIZE 4096 +#define IBUFSIZE 256 +#endif + +extern int current_font_type; +extern char *fn_proverb; +extern userinfo_t *currutmp; +extern unsigned int currstat; +extern pid_t currpid; +extern int errno; +extern screenline_t *big_picture; +extern int t_lines, t_columns; /* Screen size / width */ +extern int curr_idle_timeout; +extern water_t water[6], *swater[5], *water_which; +extern char water_usies; + +static char outbuf[OBUFSIZE], inbuf[IBUFSIZE]; +static int obufsize = 0, ibufsize = 0; +static int icurrchar = 0; + +/* ----------------------------------------------------- */ +/* �w����ܰʺA�ݪO */ +/* ----------------------------------------------------- */ +extern userec_t cuser; + +static void hit_alarm_clock() { + if(HAS_PERM(PERM_NOTIMEOUT) || PERM_HIDE(currutmp) || currstat == MAILALL) + return; +// if(time(0) - currutmp->lastact > IDLE_TIMEOUT - 2) { + if(time(0) - currutmp->lastact > curr_idle_timeout - 2) { + clear(); + if(currpid > 0) kill(currpid, SIGHUP); + } +// alarm(IDLE_TIMEOUT); + alarm(curr_idle_timeout); +} + +void init_alarm() { + signal(SIGALRM, (void (*)(int))hit_alarm_clock); +// alarm(IDLE_TIMEOUT); + alarm(curr_idle_timeout); +} + +/* ----------------------------------------------------- */ +/* output routines */ +/* ----------------------------------------------------- */ + +void oflush() { + if(obufsize) { + write(1, outbuf, obufsize); + obufsize = 0; + } +} + +void init_buf() +{ + + memset(inbuf,0,IBUFSIZE); +} +void output(char *s, int len) { + /* Invalid if len >= OBUFSIZE */ + + if(obufsize + len > OBUFSIZE) { + write(1, outbuf, obufsize); + obufsize = 0; + } + memcpy(outbuf + obufsize, s, len); + obufsize += len; +} + +int ochar(int c) { + if(obufsize > OBUFSIZE - 1) { + 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() { + return icurrchar - ibufsize; +} + +int watermode = -1; +/* Ptt ���y�^�U�Ϊ��Ѽ� */ +/* watermode = -1 �S�b�^���y + = 0 �b�^�W�@�����y (Ctrl-R) + > 0 �b�^�e n �����y (Ctrl-R Ctrl-R) */ + +/* + 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() { + int len; + + 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) */ + + 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) + return I_TIMEOUT; + + if(i_newfd && FD_ISSET(i_newfd, &readfds)) + return I_OTHERDATA; + } + + while((len = read(0, inbuf, IBUFSIZE)) <= 0) { + if(len == 0 || errno != EINTR) + abort_bbs(0); + /* raise(SIGHUP); */ + } + ibufsize = len; + icurrchar = 0; + } + + if(currutmp) + currutmp->lastact = time(0); + return inbuf[icurrchar++]; +} + +static int water_which_flag=0; +int igetch() { + register int ch; + while((ch = dogetch())) { + switch(ch) { + case Ctrl('L'): + redoscr(); + continue; + case Ctrl('U'): + if(currutmp != NULL && currutmp->mode != EDITING + && currutmp->mode != LUSERS && currutmp->mode) { + + screenline_t *screen0 = calloc(t_lines, sizeof(screenline_t)); + int y, x, my_newfd; + + getyx(&y, &x); + memcpy(screen0, big_picture, t_lines * sizeof(screenline_t)); + my_newfd = i_newfd; + i_newfd = 0; + t_users(); + i_newfd = my_newfd; + memcpy(big_picture, screen0, t_lines * sizeof(screenline_t)); + move(y, x); + free(screen0); + redoscr(); + continue; + } else + return (ch); + case KEY_TAB: + if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ) + if( currutmp != NULL && watermode > 0 ){ + watermode = (watermode + water_which->count) + % water_which->count + 1; + t_display_new(); + continue; + } + return ch; + break; + + case Ctrl('R'): + if(currutmp == NULL) + return (ch); + if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ){ + 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(currutmp->msgs[0].pid) { + /* �Ĥ@���� Ctrl-R (�������Q��L���y) */ + screenline_t *screen0; + int y, x, my_newfd; + screen0 = calloc(t_lines, sizeof(screenline_t)); + getyx(&y, &x); + memcpy(screen0, big_picture, t_lines*sizeof(screenline_t)); + + /* �p�G���btalk���ܥ����B�z���e�L�Ӫ��ʥ] (���hselect) */ + my_newfd = i_newfd; + i_newfd = 0; + show_last_call_in(0); + watermode = 0; + my_write(currutmp->msgs[0].pid, "���y��L�h �G ", + currutmp->msgs[0].userid, 0); + i_newfd = my_newfd; + + /* �٭�ù� */ + memcpy(big_picture, screen0, t_lines*sizeof(screenline_t)); + move(y, x); + free(screen0); + redoscr(); + continue; + } + else + return ch; + } + + if( currutmp->msgs[0].pid && + WATERMODE(WATER_OFO) && watermode == -1 ){ + int y, x, my_newfd; + screenline_t *screen0 = calloc(t_lines, sizeof(screenline_t)); + memcpy(screen0, big_picture, t_lines * sizeof(screenline_t)); + getyx(&y, &x); + my_newfd = i_newfd; + i_newfd = 0; + my_write2(); + memcpy(big_picture, screen0, t_lines * sizeof(screenline_t)); + i_newfd = my_newfd; + move(y, x); + free(screen0); + redoscr(); + continue; + } + + return ch; + case '\n': /* Ptt�� \n���� */ + continue; + case Ctrl('T'): + if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ){ + if(watermode > 0) { + if(watermode>1) + watermode--; + else + watermode = water_which->count; + t_display_new(); + continue; + } + } + return (ch); + + case Ctrl('E'): + if( WATERMODE(WATER_ORIG) || WATERMODE(WATER_NEW) ){ + if(watermode >0){ + 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('W'): + if(watermode >0) + { + 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; + } + else return ch; + default: + return ch; + } + } + return 0; +} + +int oldgetdata(int line, int col, char *prompt, char *buf, int len, int echo) { + register int ch, i; + int clen; + int x = col, y = line; + extern unsigned char scr_cols; +#define MAXLASTCMD 12 + static char lastcmd[MAXLASTCMD][80]; + + strip_ansi(buf, buf, STRIP_ALL); + + if(prompt) { + + move(line, col); + + clrtoeol(); + + outs(prompt); + + x += strip_ansi(NULL,prompt,0); + } + + if(!echo) { + len--; + clen = 0; + while((ch = igetch()) != '\r') { + if(ch == '\177' || ch == Ctrl('H')) { + if(!clen) { + bell(); + continue; + } + clen--; + if(echo) { + ochar(Ctrl('H')); + ochar(' '); + ochar(Ctrl('H')); + } + continue; + } +// Ptt +#ifdef BIT8 + if(!isprint2(ch)) +#else + if(!isprint(ch)) +#endif + { + if(echo) + bell(); + continue; + } + + if(clen >= len) { + if(echo) + bell(); + continue; + } + buf[clen++] = ch; + if(echo) + ochar(ch); + } + buf[clen] = '\0'; + outc('\n'); + oflush(); + } else { + int cmdpos = -1; + int currchar = 0; + + standout(); + for(clen = len--; clen; clen--) + outc(' '); + standend(); + buf[len] = 0; + move(y, x); + edit_outs(buf); + clen = currchar = strlen(buf); + + while(move(y, x + currchar), (ch = igetkey()) != '\r') { + switch(ch) { + case KEY_DOWN: + case Ctrl('N'): + buf[clen] = '\0'; /* Ptt */ + strncpy(lastcmd[cmdpos], buf, 79); + cmdpos += MAXLASTCMD - 2; + case Ctrl('P'): + case KEY_UP: + if(ch == KEY_UP || ch == Ctrl('P')) { + buf[clen] = '\0'; /* Ptt */ + strncpy(lastcmd[cmdpos], buf, 79); + } + cmdpos++; + cmdpos %= MAXLASTCMD; + strncpy(buf, lastcmd[cmdpos], len); + buf[len] = 0; + + move(y, x); /* clrtoeof */ + for(i = 0; i <= clen; i++) + outc(' '); + move(y, x); + edit_outs(buf); + clen = currchar = strlen(buf); + break; + case KEY_LEFT: + if(currchar) + --currchar; + break; + case KEY_RIGHT: + if(buf[currchar]) + ++currchar; + break; + case '\177': + case Ctrl('H'): + if(currchar) { + currchar--; + clen--; + for(i = currchar; i <= clen; i++) + buf[i] = buf[i + 1]; + move(y, x + clen); + outc(' '); + move(y, x); + edit_outs(buf); + } + break; + case Ctrl('Y'): + currchar = 0; + case Ctrl('K'): + buf[currchar] = 0; + move(y, x + currchar); + for(i = currchar; i < clen; i++) + outc(' '); + clen = currchar; + break; + case Ctrl('D'): + if(buf[currchar]) { + clen--; + for(i = currchar; i <= clen; i++) + buf[i] = buf[i + 1]; + move(y, x + clen); + outc(' '); + move(y, x); + edit_outs(buf); + } + break; + case Ctrl('A'): + currchar = 0; + break; + case Ctrl('E'): + currchar = clen; + break; + default: + if(isprint2(ch) && clen < len && x + clen < scr_cols) { + for(i = clen + 1; i > currchar;i--) + buf[i] = buf[i - 1]; + buf[currchar] = ch; + move(y, x + currchar); + edit_outs(buf + currchar); + currchar++; + clen++; + } + break; + }/* end case */ + } /* end while */ + + if(clen > 1) + for(cmdpos = MAXLASTCMD - 1; cmdpos; cmdpos--) { + strcpy(lastcmd[cmdpos], lastcmd[cmdpos - 1]); + strncpy(lastcmd[0], buf, len); + } + if(echo) + outc('\n'); + refresh(); + } + if((echo == LCECHO) && ((ch = buf[0]) >= 'A') && (ch <= 'Z')) + buf[0] = ch | 32; +#ifdef SUPPORT_GB + if(echo == DOECHO && current_font_type == TYPE_GB) + { + strcpy(buf,hc_convert_str(buf, HC_GBtoBIG, HC_DO_SINGLE)); + } +#endif + return clen; +} + +/* Ptt */ +int getdata_buf(int line, int col, char *prompt, char *buf, int len, int echo) { + return oldgetdata(line, col, prompt, buf, len, echo); +} + +char +getans(char *prompt) +{ + char ans[5]; + + getdata(t_lines-1, 0, prompt, ans, 4, LCECHO); + return ans[0]; +} + +int getdata_str(int line, int col, char *prompt, char *buf, int len, int echo, char *defaultstr) { + strncpy(buf, defaultstr, len); + + buf[len] = 0; + return oldgetdata(line, col, prompt, buf, len, echo); +} + +int getdata(int line, int col, char *prompt, char *buf, int len, int echo) { + buf[0] = 0; + return oldgetdata(line, col, prompt, buf, len, echo); +} + +int +rget(int x,char *prompt) +{ + register int ch; + + move(x,0); + clrtobot(); + outs(prompt); + refresh(); + + ch = igetch(); + if( ch >= 'A' && ch <= 'Z') ch |= 32; + + return ch; +} + + +int KEY_ESC_arg; + +int igetkey() { + int mode; + int ch, last; + + mode = last = 0; + while(1) { + ch = igetch(); + if(mode == 0) { + if(ch == KEY_ESC) + mode = 1; + else + return ch; /* Normal Key */ + } else if (mode == 1) { /* Escape sequence */ + if(ch == '[' || ch == 'O') + mode = 2; + else if(ch == '1' || ch == '4') + mode = 3; + else { + KEY_ESC_arg = ch; + return KEY_ESC; + } + } else if(mode == 2) { /* Cursor key */ + if(ch >= 'A' && ch <= 'D') + return KEY_UP + (ch - 'A'); + else if(ch >= '1' && ch <= '6') + mode = 3; + else + return ch; + } else if (mode == 3) { /* Ins Del Home End PgUp PgDn */ + if(ch == '~') + return KEY_HOME + (last - '1'); + else + return ch; + } + last = ch; + } +} + diff --git a/mbbsd/kaede.c b/mbbsd/kaede.c new file mode 100644 index 00000000..c0bd5103 --- /dev/null +++ b/mbbsd/kaede.c @@ -0,0 +1,95 @@ +/* $Id: kaede.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "proto.h" + +extern struct utmpfile_t *utmpshm; +extern userec_t cuser; + +char *Ptt_prints(char *str, int mode) { + char *po , strbuf[256]; + + while((po = strstr(str, "\033*s"))) { + po[0] = 0; + sprintf(strbuf, "%s%s%s", str, cuser.userid, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*t"))) { + time_t now = time(0); + + po[0] = 0; + sprintf(strbuf, "%s%s", str, Cdate(&now)); + str[strlen(strbuf)-1] = 0; + strcat(strbuf, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*u"))) { + int attempts; + + attempts = utmpshm->number; + po[0] = 0; + sprintf(strbuf, "%s%d%s", str, attempts, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*b"))) { + po[0] = 0; + sprintf(strbuf, "%s%d/%d%s", str, cuser.month, cuser.day, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*l"))) { + po[0] = 0; + sprintf(strbuf, "%s%d%s", str, cuser.numlogins, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*p"))) { + po[0] = 0; + sprintf(strbuf, "%s%d%s", str, cuser.numposts, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*n"))) { + po[0] = 0; + sprintf(strbuf, "%s%s%s", str, cuser.username, po + 3); + strcpy(str, strbuf); + } + while((po = strstr(str, "\033*m"))) { + po[0] = 0; + sprintf(strbuf, "%s%d%s", str, cuser.money, po + 3); + strcpy(str, strbuf); + } + strip_ansi(str, str ,mode); + return str; +} + +int Rename(char* src, char* dst) { + if(rename(src, dst) == 0) + return 0; + return -1; +} + +int Link(char* src, char* dst) { + char cmd[200]; + + if(strcmp(src, BBSHOME "/home") == 0) + return 1; + if(link(src, dst) == 0) + return 0; + + sprintf(cmd, "/bin/cp -R %s %s", src, dst); + return system(cmd); +} + +char *my_ctime(const time_t *t) { + struct tm *tp; + static char ans[100]; + + tp = localtime(t); + sprintf(ans, "%02d/%02d/%02d %02d:%02d:%02d", (tp->tm_year % 100), + tp->tm_mon + 1,tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec); + return ans; +} diff --git a/mbbsd/lovepaper.c b/mbbsd/lovepaper.c new file mode 100644 index 00000000..52e8cbd5 --- /dev/null +++ b/mbbsd/lovepaper.c @@ -0,0 +1,120 @@ +/* $Id: lovepaper.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "proto.h" + +#define DATA "etc/lovepaper.dat" + +extern userec_t cuser; + +int x_love() { + char buf1[200], save_title[TTLEN + 1]; + char receiver[61], path[STRLEN] = "home/"; + int x, y = 0, tline = 0, poem = 0; + FILE *fp, *fpo; + time_t timenow; + struct tm *gtime; + fileheader_t mhdr; + + setutmpmode(LOVE); + time(&timenow); + gtime = localtime(&timenow); + sprintf(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 �� \n"); + outs("�������H�Ҿ�����,��Ѩt�����A���a.\n������ : �ݱ����Ǫk.\n"); + + if(!getdata(7, 0, "���H�H�G", receiver, 60, DOECHO)) return 0; + if(receiver[0] && !(searchuser(receiver) && + getdata(8, 0, "�D �D�G", save_title, + TTLEN, DOECHO))) { + move(10, 0); + outs("���H�H�ΥD�D�����T, ���ѵL�k�ǻ�. "); + pressanykey(); + return 0; + } + + fpo = fopen(path, "w"); + 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 = (rand() % (x - 1)) * tline; + break; + default: + if(!poem) { + if(y > 0) + y = y - 1; + else { + if(tline > 0) { + fprintf(fpo, "%s", buf1); + tline--; + } + } + } else { + if(buf1[0] == '$') + y--; + else if(y == 0) + fprintf(fpo,"%s",buf1); + } + } + + } + + fclose(fp); + fclose(fpo); + if(vedit(path, YEA, NULL) == -1) { + unlink(path); + clear(); + outs("\n\n ���H����\n"); + pressanykey(); + return -2; + } + sethomepath(buf1, receiver); + stampfile(buf1, &mhdr); + Rename(path, buf1); + strncpy(mhdr.title, save_title, TTLEN); + strcpy(mhdr.owner, cuser.userid); + mhdr.savemode = '\0'; + sethomedir(path, receiver ); + if(append_record(path, &mhdr, sizeof(mhdr)) == -1) + return -1; + hold_mail(buf1, receiver); + return 1; + } + return 0; +} diff --git a/mbbsd/mail.c b/mbbsd/mail.c new file mode 100644 index 00000000..e480abb2 --- /dev/null +++ b/mbbsd/mail.c @@ -0,0 +1,1675 @@ +/* $Id: mail.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +extern int TagNum; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char save_title[]; /* used by editor when inserting */ +extern int curredit; +extern char *err_uid; +extern char *msg_cancel; +extern char *msg_uid; +extern char *fn_overrides; +extern char quote_file[80]; +extern char quote_user[80]; +extern char *fn_notes; +extern char *msg_mailer; +extern char *msg_sure_ny; +extern char *BBSName; +extern char currtitle[44]; +extern unsigned char currfmode; /* current file mode */ +extern char *msg_del_ny; +extern char currfile[FNLEN]; +extern int currmode; +extern char currboard[]; /* name of currently selected board */ +extern char *str_space; +extern char *str_author1; +extern char *str_author2; +extern userinfo_t *currutmp; +extern unsigned int currstat; +extern pid_t currpid; +extern int usernum; +extern char *str_mail_address; +extern userec_t cuser; + +char currmaildir[32]; +static char msg_cc[] = "\033[32m[�s�զW��]\033[m\n"; +static char listfile[] = "list.0"; +static int mailkeep = 0, mailsum = 0; +static int mailsumlimit = 0,mailmaxkeep = 0; + +int setforward() { + char buf[80], ip[50] = "", yn[4]; + FILE *fp; + + sethomepath(buf, cuser.userid); + strcat(buf,"/.forward"); + if((fp = fopen(buf,"r"))) { + fscanf(fp,"%s",ip); + fclose(fp); + } + getdata_buf(b_lines - 1, 0, "�п�J�H�c�۰���H��email�a�}:", + ip, 41, DOECHO); + if(ip[0] && ip[0] != ' ') { + getdata(b_lines, 0, "�T�w�}�Ҧ۰���H�\\��?(Y/n)", yn, 3, + LCECHO); + if(yn[0] != 'n' && (fp = fopen(buf, "w"))) { + move(b_lines,0); + clrtoeol(); + fprintf(fp,"%s",ip); + fclose(fp); + outs("�]�w����!"); + refresh(); + return 0; + } + } + move(b_lines,0); + clrtoeol(); + outs("�����۰���H!"); + unlink(buf); + refresh(); + return 0; +} + +int built_mail_index() { + char genbuf[128]; + + getdata(b_lines, 0, + "���ثH�c?(ĵ�i:�нT�w�H�c�����D�ɤ~�ϥ�)(y/N)", genbuf, 3, + LCECHO); + if(genbuf[0] != 'y') return 0; + + sprintf(genbuf, BBSHOME "/bin/buildir " BBSHOME "/home/%c/%s", + cuser.userid[0], cuser.userid); + move(22,0); + prints("\033[1;31m�w�g�B�z����!! �Ѧh���K �q�Э��~\033[m");pressanykey(); + system(genbuf); + return 0; +} + +int mailalert(char *userid) +{ + userinfo_t *uentp=NULL; + int n,tuid,i; + + if((tuid=searchuser(userid))==0) return -1; + + n=count_logins(tuid, 0); + for(i=1;i<=n;i++) + if((uentp = (userinfo_t *)search_ulistn(tuid, i))) + uentp->mailalert=1; + return 0; +} + +int mail_muser(userec_t muser, char *title, char *filename) { + return mail_id(muser.userid, title, filename, cuser.userid); +} + +/* Heat: ��id�ӱH�H,���e�hlink�dzƦn���ɮ� */ +int mail_id(char* id, char *title, char *filename, char *owner) { + fileheader_t mhdr; + char genbuf[128]; + sethomepath(genbuf, id); + if(stampfile(genbuf, &mhdr)) + return 0; + strcpy(mhdr.owner, owner); + strncpy(mhdr.title, title, TTLEN); + mhdr.savemode = 0; + mhdr.filemode = 0; + Link(filename, genbuf); + sethomedir(genbuf,id); + append_record(genbuf, &mhdr, sizeof(mhdr)); + mailalert(id); + return 0; +} + +int invalidaddr(char *addr) { + if(*addr == '\0') + return 1; /* blank */ + while(*addr) { + if(not_alnum(*addr) && !strchr("[].%!@:-_;", *addr)) + return 1; + addr++; + } + return 0; +} + +int m_internet() { + char receiver[60]; + + getdata(20, 0, "���H�H�G", receiver, 60, DOECHO); + if(strchr(receiver, '@') && !invalidaddr(receiver) && + getdata(21, 0, "�D �D�G", save_title, TTLEN, DOECHO)) + do_send(receiver, save_title); + else { + move(22, 0); + outs("���H�H�ΥD�D�����T, �Э��s������O"); + pressanykey(); + } + return 0; +} + +void m_init() { + sethomedir(currmaildir, cuser.userid); +} + +int chkmailbox() { + if(!HAVE_PERM(PERM_SYSOP) && !HAVE_PERM(PERM_MAILLIMIT)) { + int max_keepmail = MAX_KEEPMAIL; + if ( HAS_PERM(PERM_SYSSUBOP) || HAS_PERM(PERM_SMG) || + HAS_PERM(PERM_PRG) || HAS_PERM(PERM_ACTION) || HAS_PERM(PERM_PAINT)) + { + mailsumlimit = 700; + max_keepmail = 500; + } + else if(HAS_PERM(PERM_BM)) + { + mailsumlimit = 500; + max_keepmail = 300; + } + else if(HAS_PERM(PERM_LOGINOK)) + mailsumlimit = 200; + else + mailsumlimit = 50; + mailsumlimit += cuser.exmailbox * 10; + mailmaxkeep = max_keepmail + cuser.exmailbox; + m_init(); + if((mailkeep = get_num_records(currmaildir, sizeof(fileheader_t))) > + mailmaxkeep) { + move(b_lines, 0); + clrtoeol(); + bell(); + prints("�z�O�s�H��ƥ� %d �W�X�W�� %d, �о�z", + mailkeep, mailmaxkeep); + bell(); + refresh(); + igetch(); + return mailkeep; + } + if((mailsum = get_sum_records(currmaildir, sizeof(fileheader_t))) > + mailsumlimit) { + move(b_lines, 0); + clrtoeol(); + bell(); + prints("�z�O�s�H��e�q %d(k)�W�X�W�� %d(k), �о�z", + mailsum, mailsumlimit); + bell(); + refresh(); + igetch(); + return mailkeep; + } + } + return 0; +} + +static void do_hold_mail(char *fpath, char *receiver, char *holder) { + char buf[80], title[128]; + + fileheader_t mymail; + + sethomepath(buf, holder); + stampfile(buf, &mymail); + + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, "[��.��.��]"); + if(receiver) { + sprintf(title, "(%s) %s", receiver, save_title); + strncpy(mymail.title, title, TTLEN); + } else + strcpy(mymail.title, save_title); + + sethomedir(title, holder); + + unlink(buf); + Link(fpath, buf); + /* Ptt: append_record->do_append */ + do_append(title, &mymail, sizeof(mymail)); +} + +extern userec_t xuser; + +void hold_mail(char *fpath, char *receiver) { + char buf[4]; + + getdata(b_lines - 1, 0, "�w���Q�H�X�A�O�_�ۦs���Z(Y/N)�H[N] ", + buf, 4, LCECHO); + + if(buf[0] == 'y') + do_hold_mail(fpath, receiver, cuser.userid); +} + +int do_send(char *userid, char *title) { + fileheader_t mhdr; + char fpath[STRLEN]; + char receiver[IDLEN]; + char genbuf[200]; + int internet_mail, i; + + if(strchr(userid, '@')) + internet_mail = 1; + else { + internet_mail = 0; + if(!getuser(userid)) + return -1; + if(!(xuser.userlevel & PERM_READMAIL)) + return -3; + + if(!title) + getdata(2, 0, "�D�D�G", save_title, TTLEN, DOECHO); + curredit |= EDIT_MAIL; + curredit &= ~EDIT_ITEM; + } + + 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�w�n�H�X��? (Y/N) [Y]", + userid, 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, title, userid); +#else + bsmtp(fpath, title, userid,0); +#endif + hold_mail(fpath, userid); + } + unlink(fpath); + return res; + } else { + strcpy(receiver, userid); + sethomepath(genbuf, userid); + stampfile(genbuf, &mhdr); + strcpy(mhdr.owner, cuser.userid); + strncpy(mhdr.title, save_title, TTLEN); + mhdr.savemode = '\0'; + if(vedit(genbuf, YEA, NULL) == -1) { + unlink(genbuf); + clear(); + return -2; + } + 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(fpath, &mhdr, sizeof(mhdr)) == -1) + return -1; + mailalert(userid); + } + hold_mail(genbuf, userid); + return 0; + } +} + +void my_send(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() { + 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 */ +extern struct word_t *toplev; + +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); + getdata(1, 0, + "(I)�ޤJ�n�� (O)�ޤJ�W�u�q�� (N)�ޤJ�s�峹�q�� " + "(0-9)�ޤJ��L�S�O�W��\n" + "(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("�п�J�n�W�[���N��(�u�� ENTER �����s�W): ", uid); + if(uid[0] == '\0') + break; + + move(2, 0); + clrtoeol(); + + if(!searchuser(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("�п�J�n�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; + 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"); + while(fgets(genbuf, 256, fp)) { + if(strncmp(genbuf, "�� ", 3)) { + if(listing) + break; + } else { + if(listing) { + strtok(ptr = genbuf + 3, " \n\r"); + do { + if(searchuser(ptr) && !InNameList(ptr) && + strcmp(cuser.userid, ptr)) { + AddNameList(ptr); + reciper++; + } + } while((ptr = (char *)strtok(NULL, " \n\r"))); + } else if(!strncmp(genbuf + 3, "[�q�i]", 6)) + listing = 1; + } + } + 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, 64, DOECHO); + sprintf(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; + outs(msg_cancel); + pressanykey(); + return; + } + + stand_title("�H�H��..."); + refresh(); + + 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) && strcmp(STR_GUEST, p->word) ) + sethomepath(genbuf, p->word); + else + continue; + stampfile(genbuf, &mymail); + unlink(genbuf); + Link(fpath, genbuf); + + strcpy(mymail.owner, cuser.userid); + strcpy(mymail.title, save_title); + mymail.savemode = 'M'; /* multi-send flag */ + sethomedir(genbuf, p->word); + if(append_record(genbuf, &mymail, sizeof(mymail)) == -1) + outs(err_uid); + mailalert(p->word); + } + hold_mail(fpath, NULL); + unlink(fpath); + curredit = 0; + } else + outs(msg_cancel); + pressanykey(); +} + +static int multi_reply(int ent, fileheader_t *fhdr, char *direct) { + if(fhdr->savemode != 'M') + return mail_reply(ent, fhdr, direct); + + stand_title("�s�զ^�H"); + strcpy(quote_user, fhdr->owner); + setuserfile(quote_file, fhdr->filename); + multi_send(fhdr->title); + return 0; +} + +int mail_list() { + stand_title("�s�է@�~"); + multi_send(NULL); + return 0; +} + +int mail_all() { + FILE *fp; + fileheader_t mymail; + char fpath[TTLEN]; + char genbuf[200]; + extern struct uhash_t *uhash; + int i, unum; + char *userid; + + stand_title("���Ҧ��ϥΪ̪��t�γq�i"); + setutmpmode(SMAIL); + getdata(2, 0, "�D�D�G", fpath, 64, DOECHO); + sprintf(save_title, "[�t�γq�i]\033[1;32m %s\033[m", fpath); + + setuserfile(fpath, fn_notes); + + if((fp = fopen(fpath, "w"))) { + fprintf(fp, "�� [\033[1m�t�γq�i\033[m] �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); + Link(fpath, genbuf); + unlink(fpath); + strcpy(fpath, genbuf); + + strcpy(mymail.owner, cuser.userid); /*���� ID*/ + strcpy(mymail.title, save_title); + mymail.savemode = 0; + + sethomedir(genbuf, cuser.userid); + if(append_record(genbuf, &mymail, sizeof(mymail)) == -1) + outs(err_uid); + + for(unum = uhash->number, i = 0; i < unum; i++) { + if(bad_user_id(uhash->userid[i])) + continue; /* Ptt */ + + userid = uhash->userid[i]; + if(strcmp(userid,STR_GUEST) && strcmp(userid, "new") && + strcmp(userid, cuser.userid)) { + sethomepath(genbuf, userid); + stampfile(genbuf, &mymail); + unlink(genbuf); + Link(fpath, genbuf); + + strcpy(mymail.owner, cuser.userid); + strcpy(mymail.title, save_title); + mymail.savemode = 0; + /* mymail.filemode |= FILE_MARKED; Ptt ���i�令���|mark */ + sethomedir(genbuf, userid); + if(append_record(genbuf, &mymail, sizeof(mymail)) == -1) + outs(err_uid); + sprintf(genbuf, "%*s %5d / %5d", IDLEN + 1, userid, i + 1, unum); + outmsg(genbuf); + refresh(); + } + } + return 0; +} + +int mail_mbox() { + char cmd[100]; + fileheader_t fhdr; + + sprintf(cmd, "/tmp/%s.uu", cuser.userid); + sprintf(fhdr.title, "%s �p�H���", cuser.userid); + doforward(cmd, &fhdr, 'Z'); + return 0; +} + +static int m_forward(int ent, fileheader_t *fhdr, char *direct) { + char uid[STRLEN]; + + stand_title("��F�H��"); + usercomplete(msg_uid, uid); + if(uid[0] == '\0') + return FULLUPDATE; + + strcpy(quote_user, fhdr->owner); + setuserfile(quote_file, fhdr->filename); + sprintf(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(); + return FULLUPDATE; +} + +static int delmsgs[128]; +static int delcnt; +static int mrd; + +static int read_new_mail(fileheader_t *fptr) { + static int idc; + char done = NA, delete_it; + char fname[256]; + char genbuf[4]; + + if(fptr == NULL) { + delcnt = 0; + idc = 0; + return 0; + } + idc++; + if(fptr->filemode) + return 0; + clear(); + move(10, 0); + prints("�z�nŪ�Ӧ�[%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), idc)) + return -1; + + mrd = 1; + delete_it = NA; + while(!done) { + int more_result = more(fname, YEA); + + switch(more_result) { + case 1: + return READ_PREV; + case 2: + return RELATE_PREV; + case 3: + return READ_NEXT; + case 4: + return RELATE_NEXT; + case 5: + return RELATE_FIRST; + case 6: + return 0; + case 7: + mail_reply(idc, fptr, currmaildir); + return FULLUPDATE; + case 8: + multi_reply(idc, fptr, currmaildir); + return FULLUPDATE; + } + move(b_lines, 0); + clrtoeol(); + outs(msg_mailer); + refresh(); + + switch(egetch()) { + case 'r': + case 'R': + mail_reply(idc, fptr, currmaildir); + break; + case 'x': + m_forward(idc, fptr, currmaildir); + break; + case 'y': + multi_reply(idc, fptr, currmaildir); + break; + case 'd': + case 'D': + delete_it = YEA; + default: + done = YEA; + } + } + if(delete_it) { + clear(); + prints("�R���H��m%s�n", fptr->title); + getdata(1, 0, msg_sure_ny, genbuf, 2, LCECHO); + if(genbuf[0] == 'y') { + unlink(fname); + delmsgs[delcnt++] = idc; + } + } + clear(); + return 0; +} + +int m_new() { + clear(); + mrd = 0; + setutmpmode(RMAIL); + read_new_mail(NULL); + clear(); + curredit |= EDIT_MAIL; + curredit &= ~EDIT_ITEM; + if(apply_record(currmaildir, read_new_mail, sizeof(fileheader_t)) == -1) { + outs("�S���s�H��F"); + pressanykey(); + return -1; + } + curredit = 0; + if(delcnt) { + while(delcnt--) + delete_record(currmaildir, sizeof(fileheader_t), delmsgs[delcnt]); + } + outs(mrd ? "�H�w�\\��" : "�S���s�H��F"); + pressanykey(); + return -1; +} + +static void mailtitle() { + char buf[256] = ""; + + showtitle("\0�l����", BBSName); + sprintf(buf,"[��]���}[����]���[��]�\\Ū�H�� [R]�^�H [x]��F " + "[y]�s�զ^�H [O]���~�H:%s [h]�D�U\n\033[7m" + "�s�� �� �� �@ �� �H �� �� �D \033[32m", + HAS_PERM(PERM_NOOUTMAIL)? "\033[31m��\033[m":"�}"); + outs(buf); + buf[0]=0; + if(mailsumlimit) { + sprintf(buf,"(�e�q:%d/%dk %d/%d�g)", mailsum, mailsumlimit, + mailkeep, mailmaxkeep); + } + sprintf(buf, "%s%*s\033[m", buf, 29 - (int) strlen(buf), ""); + outs(buf); +} + +static void maildoent(int num, fileheader_t *ent) { + char *title, *mark, color, type = "+ Mm"[ent->filemode]; + + if (TagNum && !Tagger(atoi(ent->filename + 2), 0, TAG_NIN)) + type = 'D'; + + title = subject(mark = ent->title); + if(title == mark) { + color = '1'; + mark = "��"; + } else { + color = '3'; + mark = "R:"; + } + + if(strncmp(currtitle, title, 40)) + prints("%5d %c %-7s%-15.14s%s %.46s\n", num, type, + ent->date, ent->owner, mark, title); + else + prints("%5d %c %-7s%-15.14s\033[1;3%cm%s %.46s\033[0m\n", num, type, + ent->date, ent->owner, color, mark, title); +} + +#ifdef POSTBUG +extern int bug_possible; +#endif + + +static int m_idle(int ent, fileheader_t *fhdr, char *direct) { + t_idle(); + return FULLUPDATE; +} + +static int mail_del(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[200]; + + if(fhdr->filemode & FILE_MARKED) + return DONOTHING; + + getdata(1, 0, msg_del_ny, genbuf, 3, LCECHO); + if(genbuf[0] == 'y') { + strcpy(currfile, fhdr->filename); + if(!delete_file(direct, sizeof(*fhdr), ent, cmpfilename)) { + setdirpath(genbuf, direct, fhdr->filename); + unlink(genbuf); + if((currmode & MODE_SELECT)) { + int now; + + sethomedir(genbuf, cuser.userid); + now = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); + delete_file(genbuf, sizeof(fileheader_t), now, cmpfilename); + } + return DIRCHANGED; + } + } + return FULLUPDATE; +} + +static int mail_read(int ent, fileheader_t *fhdr, char *direct) { + char buf[64]; + char done, delete_it, replied; + + clear(); + setdirpath(buf, direct, fhdr->filename); + strncpy(currtitle, subject(fhdr->title), 40); + done = delete_it = replied = NA; + while(!done) { + int more_result = more(buf, YEA); + + if(more_result != -1) { + fhdr->filemode |= FILE_READ; + if((currmode & MODE_SELECT)) { + int now; + + now = getindex(currmaildir, fhdr->filename, + sizeof(fileheader_t)); + substitute_record(currmaildir, fhdr, sizeof(*fhdr), now); + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + } + else + substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent); + } + switch(more_result) { + case 1: + return READ_PREV; + case 2: + return RELATE_PREV; + case 3: + return READ_NEXT; + case 4: + return RELATE_NEXT; + case 5: + return RELATE_FIRST; + case 6: + return FULLUPDATE; + case 7: + mail_reply(ent, fhdr, direct); + return FULLUPDATE; + case 8: + multi_reply(ent, fhdr, direct); + return FULLUPDATE; + } + move(b_lines, 0); + clrtoeol(); + refresh(); + outs(msg_mailer); + + switch(egetch()) { + case 'r': + case 'R': + replied = YEA; + mail_reply(ent, fhdr, direct); + break; + case 'x': + m_forward(ent, fhdr, direct); + break; + case 'y': + multi_reply(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; +#ifdef POSTBUG + if(replied) + bug_possible = YEA; +#endif + if((currmode & MODE_SELECT)) { + int now; + + now = getindex(currmaildir, fhdr->filename, sizeof(fileheader_t)); + substitute_record(currmaildir, fhdr, sizeof(*fhdr), now); + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + } else + substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent); +#ifdef POSTBUG + bug_possible = NA; +#endif + } + return FULLUPDATE; +} + +/* in boards/mail �^�H����@�̡A��H����i */ +int mail_reply(int ent, fileheader_t *fhdr, char *direct) { + char uid[STRLEN]; + char *t; + FILE *fp; + char genbuf[512]; + + 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 */ + strcpy(quote_user, fhdr->owner); + if(strchr(quote_user, '.')) { + genbuf[0] = '\0'; + if((fp = fopen(quote_file, "r"))) { + fgets(genbuf, 512, fp); + fclose(fp); + } + + t = strtok(genbuf, str_space); + if(!strcmp(t, str_author1) || !strcmp(t, str_author2)) + strcpy(uid, strtok(NULL, str_space)); + else { + outs("���~: �䤣��@�̡C"); + pressanykey(); + return FULLUPDATE; + } + } else + strcpy(uid, quote_user); + + /* 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; + } + curredit = ent; + pressanykey(); + return FULLUPDATE; +} + +static int mail_edit(int ent, fileheader_t *fhdr, char *direct) { + char genbuf[200]; + + if(!HAS_PERM(PERM_SYSOP) && + strcmp(cuser.userid, fhdr->owner) && + strcmp("[��.��.��]", fhdr->owner)) + return DONOTHING; + + setdirpath(genbuf, direct, fhdr->filename); + vedit(genbuf, NA, NULL); + return FULLUPDATE; +} + +static int mail_nooutmail(int ent, fileheader_t *fhdr, char *direct) +{ + cuser.userlevel ^= PERM_NOOUTMAIL; + passwd_update(usernum, &cuser); + return FULLUPDATE; + +} + +static int mail_mark(int ent, fileheader_t *fhdr, char *direct) { + fhdr->filemode ^= FILE_MARKED; + + if((currmode & MODE_SELECT)) { + int now; + + now = getindex(currmaildir, fhdr->filename, sizeof(fileheader_t)); + substitute_record(currmaildir, fhdr, sizeof(*fhdr), now); + substitute_record(direct, fhdr, sizeof(*fhdr), ent); + } else + substitute_record(currmaildir, fhdr, sizeof(*fhdr), ent); + return PART_REDRAW; +} + +/* help for mail reading */ +static char *mail_help[] = { + "\0�q�l�H�c�ާ@����", + "\01�R�O", + "(p)(��) �e�@�g�峹", + "(n)(��) �U�@�g�峹", + "(P)(PgUp) �e�@��", + "(N)(PgDn) �U�@��", + "(##)(cr) ����� ## ��", + "($) ����̫�@��", + "\01�i���R�O", + "(r)(��)/(R)Ū�H / �^�H", + "(O) ����/�}�� ���~�H����J", + "(c/z) ���J���H��i�J�p�H�H��/�i�J�p�H�H��", + "(x/X) ��F�H��/����峹���L�ݪO", + "(y) �s�զ^�H", + "(F) �N�H�ǰe�^�z���q�l�H�c (u)���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() { + show_help(mail_help); + return FULLUPDATE; +} + +static int mail_cross_post(int ent, fileheader_t *fhdr, 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]; + + make_blist(); + move(2, 0); + clrtoeol(); + move(3, 0); + clrtoeol(); + move(1, 0); + namecomplete("������峹��ݪO�G", xboard); + if(*xboard == '\0' || !haspostperm(xboard)) + return FULLUPDATE; + + ent = 1; + if(HAS_PERM(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) + sprintf(xtitle, "[���]%.66s", fhdr->title); + else + strcpy(xtitle, fhdr->title); + + sprintf(genbuf, "�ĥέ���D�m%.60s�n��?[Y] ", xtitle); + getdata(2, 0, genbuf, genbuf2, 4, LCECHO); + if(*genbuf2 == 'n') + if(getdata(2, 0, "���D�G", genbuf, TTLEN, DOECHO)) + strcpy(xtitle, genbuf); + + 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) + strcpy(xfile.owner, fhdr->owner); + else + strcpy(xfile.owner, cuser.userid); + strcpy(xfile.title, xtitle); + if(genbuf[0] == 'l') { + xfile.savemode = 'L'; + xfile.filemode = FILE_LOCAL; + } else + xfile.savemode = 'S'; + + setuserfile(fname, fhdr->filename); + if(ent) { + xptr = fopen(xfpath, "w"); + + strcpy(save_title, xfile.title); + strcpy(xfpath, currboard); + strcpy(currboard, xboard); + write_header(xptr); + strcpy(currboard, xfpath); + + fprintf(xptr, "�� [��������� %s �H�c]\n\n", cuser.userid); + + b_suckinfile(xptr, fname); + addsignature(xptr,0); + fclose(xptr); + } else { + unlink(xfpath); + Link(fname, xfpath); + } + + setbdir(fname, xboard); + append_record(fname, &xfile, sizeof(xfile)); + setbtotal(getbnum(xboard)); + if(!xfile.filemode) + outgo_post(&xfile, xboard); + cuser.numposts++; + passwd_update(usernum, &cuser); + outs("�峹�������"); + pressanykey(); + currmode = currmode0; + } + return FULLUPDATE; +} + +int mail_man() { + char buf[64],buf1[64]; + if (HAS_PERM(PERM_MAILLIMIT)) { + int mode0 = currutmp->mode; + int stat0 = currstat; + + sethomeman(buf, cuser.userid); + sprintf(buf1, "%s ���H��", cuser.userid); + a_menu(buf1, buf, 1); + currutmp->mode = mode0; + currstat = stat0; + return FULLUPDATE; + } + return DONOTHING; +} + +static int mail_cite(int ent, fileheader_t *fhdr, char *direct) { + char fpath[256]; + char title[TTLEN + 1]; + static char xboard[20]; + char buf[20]; + boardheader_t *bp; + + setuserfile(fpath, fhdr->filename); + strcpy(title, "�� "); + strncpy(title+3, fhdr->title, TTLEN-3); + title[TTLEN] = '\0'; + a_copyitem(fpath, title, 0, 1); + + if(cuser.userlevel >= PERM_BM) { + move(2, 0); + clrtoeol(); + move(3, 0); + clrtoeol(); + move(1, 0); + make_blist(); + namecomplete("��J�ݪ��W�� (����Enter�i�J�p�H�H��)�G", buf); + if(*buf) + strcpy(xboard, buf); + if(*xboard && (bp = getbcache(getbnum(xboard)))) { + setapath(fpath, xboard); + setutmpmode(ANNOUNCE); + a_menu(xboard, fpath, HAS_PERM(PERM_ALLBOARD) ? 2 : + is_BM(bp->BM) ? 1 : 0); + } else { + mail_man(); + } + return FULLUPDATE; + } else { + mail_man(); + return FULLUPDATE; + } +} + +static int mail_save(int ent, fileheader_t *fhdr, char *direct) { + char fpath[256]; + char title[TTLEN+1]; + + if(HAS_PERM(PERM_MAILLIMIT)) { + setuserfile(fpath, fhdr->filename); + strcpy(title, "�� "); + strncpy(title + 3, fhdr->title, TTLEN - 3); + title[TTLEN] = '\0'; + a_copyitem(fpath, title, fhdr->owner, 1); + sethomeman(fpath, cuser.userid); + a_menu(cuser.userid, fpath, 1); + return FULLUPDATE; + } + return DONOTHING; +} + +#ifdef OUTJOBSPOOL +static int mail_waterball(int ent, fileheader_t *fhdr, char *direct) +{ + static char address[60], cmode = 1; + char fname[500], genbuf[200]; + FILE *fp; + int now; + + if(!address[0]) + strcpy(address, cuser.email); + if(address[0]) { + sprintf(genbuf, "�H�� [%s] ��(Y/N/Q)�H[Y] ", address); + getdata(b_lines - 2, 0, genbuf, fname, 3, LCECHO); + if(fname[0] == 'q') { outmsg("�����B�z"); return 1; } + if(fname[0] == 'n') + address[0] = '\0'; + } + + if(!address[0]) { + getdata(b_lines - 2, 0, "�п�J�l��a�}�G", fname, 60, DOECHO); + if(fname[0] && strchr(fname, '.')) { + strcpy(address, fname); + } else { + outmsg("�����B�z"); + return 1; + } + } + if(invalidaddr(address)) + return -2; + + // sprintf(fname, "%d\n", cmode); + getdata(b_lines - 1, 0, "�ϥμҦ�(0/1)? [1]", fname, 3, LCECHO); + cmode = (fname[0] != '0' && fname[0] != '1') ? 1 : fname[0] - '0'; + + now = time(NULL); + sprintf(fname, BBSHOME "/jobspool/water.src.%s-%d", + cuser.userid, now); + sprintf(genbuf, "cp " BBSHOME "/home/%c/%s/%s %s", + cuser.userid[0], cuser.userid, fhdr->filename, fname); + system(genbuf); + /* dirty code ;x */ + sprintf(fname, BBSHOME "/jobspool/water.des.%s-%d", + cuser.userid, now); + fp = fopen(fname, "wt"); + fprintf(fp, "%s\n%s\n%d\n", cuser.userid, address, cmode); + fclose(fp); + return FULLUPDATE; +} +#endif +static struct onekey_t mail_comms[] = { + {'z', mail_man}, + {'c', mail_cite}, + {'s', mail_save}, + {'d', mail_del}, + {'D', del_range}, + {'r', mail_read}, + {'R', mail_reply}, + {'E', mail_edit}, + {'m', mail_mark}, + {'O', mail_nooutmail}, + {'T', edit_title}, + {'x', m_forward}, + {'X', mail_cross_post}, + {Ctrl('G'), built_mail_index}, /* �H�c */ + {'y', multi_reply}, + {Ctrl('I'), m_idle}, + {'h', m_help}, +#ifdef OUTJOBSPOOL + {'u', mail_waterball}, +#endif + {'\0', NULL} +}; + +int m_read() { + if(get_num_records(currmaildir, sizeof(fileheader_t))) { + curredit = EDIT_MAIL; + curredit &= ~EDIT_ITEM; + i_read(RMAIL, currmaildir, mailtitle, maildoent, mail_comms, -1); + curredit = 0; + currutmp->mailalert = load_mailalert(cuser.userid); + return 0; + } else { + outs("�z�S���ӫH"); + return XEASY; + } +} + +/* �H�����H */ +static int send_inner_mail(char *fpath, char *title, char *receiver) { + char genbuf[256]; + fileheader_t mymail; + + if(!searchuser(receiver)) + return -2; + sethomepath(genbuf, receiver); + stampfile(genbuf, &mymail); + if(!strcmp(receiver, cuser.userid)) { + strcpy(mymail.owner, "[" BBSNAME "]"); + mymail.filemode = FILE_READ; + } else + strcpy(mymail.owner, cuser.userid); + strncpy(mymail.title, title, TTLEN); + unlink(genbuf); + Link(fpath, genbuf); + sethomedir(genbuf, receiver); + return do_append(genbuf, &mymail, sizeof(mymail)); +} + +#include <netdb.h> +#include <pwd.h> +#include <time.h> + +#ifndef USE_BSMTP +static int bbs_sendmail(char *fpath, char *title, char *receiver) { + static int configured = 0; + static char myhostname[STRLEN]; + static char myusername[20]; + struct hostent *hbuf; + struct passwd *pbuf; + char *ptr; + char genbuf[256]; + FILE *fin, *fout; + + /* ���~�d�I */ + if((ptr = strchr(receiver, ';'))) { + struct tm *ptime; + time_t now; + + *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 + strcpy(hacker,receiver); + return send_inner_mail(fpath, title, hacker); + } + + /* setup the hostname and username */ + if(!configured) { + /* get host name */ + hbuf = gethostbyname("localhost"); + if(hbuf) + strncpy(myhostname, hbuf->h_name, STRLEN); + + /* get bbs uident */ + pbuf = getpwuid(getuid()); + if(pbuf) + strncpy(myusername, pbuf->pw_name, 20); + if(hbuf && pbuf) + configured = 1; + else + return -1; + } + + /* Running the sendmail */ + if(fpath == NULL) { + sprintf(genbuf, "/usr/sbin/sendmail %s > /dev/null", receiver); + fin = fopen("etc/confirm", "r"); + } else { + sprintf(genbuf, "/usr/sbin/sendmail -f %s%s %s > /dev/null", + cuser.userid, str_mail_address, receiver); + fin = fopen(fpath, "r"); + } + fout = popen(genbuf, "w"); + if(fin == NULL || fout == NULL) + return -1; + + if(fpath) + fprintf(fout, "Reply-To: %s%s\nFrom: %s%s\n", + cuser.userid, str_mail_address, cuser.userid, + str_mail_address); + fprintf(fout, "To: %s\nSubject: %s\n", receiver, title); + fprintf(fout, "X-Disclaimer: " BBSNAME "�糧�H���e�����t�d�C\n\n"); + + while(fgets(genbuf, 255, 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(char *fpath, char *title, char *rcpt, int method) { + char buf[80], *ptr; + time_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 + strcpy(hacker, rcpt); + return send_inner_mail(fpath, title, hacker); + } + + chrono = time(NULL); + if(method != MQ_JUSTIFY) { /* �{�ҫH */ + /* stamp the queue file */ + strcpy(buf, "out/"); + for(;;) { + sprintf(buf + 4,"M.%ld.A", ++chrono); + if(!dashf(buf)) { + Link(fpath, buf); + break; + } + } + + fpath = buf; + + strcpy(mqueue.filepath, fpath); + strcpy(mqueue.subject, title); + } + /* setup mail queue */ + mqueue.mailtime = chrono; + mqueue.method = method; + strcpy(mqueue.sender, cuser.userid); + strcpy(mqueue.username, cuser.username); + strcpy(mqueue.rcpt, rcpt); + if(do_append("out/.DIR", (fileheader_t *)&mqueue, sizeof(mqueue)) < 0) + return 0; + return chrono; +} +#endif /* USE_BSMTP */ + +int doforward(char *direct, fileheader_t *fh, int mode) { + static char address[60]; + char fname[500]; + int return_no; + char genbuf[200]; + + if(!address[0]) + strcpy(address, cuser.email); + + if(address[0]) { + sprintf(genbuf, "�T�w��H�� [%s] ��(Y/N/Q)�H[Y] ", address); + getdata(b_lines - 1, 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, '.')) + strcpy(address, fname); + else + sprintf(address, "%s.bbs@%s", fname, MYHOSTNAME); + } else { + outmsg("������H"); + return 1; + } + }while(mode=='Z' && strstr(address, MYHOSTNAME)); + } + if(invalidaddr(address)) + return -2; + + sprintf(fname, "����H�� %s, �еy��...", address); + outmsg(fname); + move(b_lines - 1, 0); + refresh(); + + /* �l�ܨϥΪ� */ + if(HAS_PERM(PERM_LOGUSER)) { + time_t now = time(NULL); + char msg[200]; + + sprintf(msg, "%s mailforward to %s at %s", + cuser.userid, address, Cdate(&now)); + log_user(msg); + } + + if(mode == 'Z') { + sprintf(fname, TAR_PATH " cfz - home/%c/%s | " + "/usr/bin/uuencode %s.tgz > %s", + cuser.userid[0], cuser.userid, cuser.userid, direct); + system(fname); + strcpy(fname, direct); + } else if(mode == 'U') { + char tmp_buf[128]; + + sprintf(fname, "/tmp/bbs.uu%05d", currpid); + sprintf(tmp_buf, "/usr/bin/uuencode %s/%s uu.%05d > %s", + direct, fh->filename, currpid, fname); + system(tmp_buf); + } else if (mode == 'F'){ + char tmp_buf[128]; + + sprintf(fname, "/tmp/bbs.f%05d", currpid); + sprintf(tmp_buf, "cp %s/%s %s",direct,fh->filename,fname); + system(tmp_buf); + } else + return -1; + + return_no = +#ifndef USE_BSMTP + bbs_sendmail(fname, fh->title, address); +#else + bsmtp(fname, fh->title, address,mode); +#endif + unlink(fname); + return (return_no); +} + +int load_mailalert(char *userid) { + struct stat st; + char maildir[256]; + int fd; + register int numfiles; + fileheader_t my_mail; + + sethomedir(maildir, userid); + if(!HAS_PERM(PERM_BASIC)) + return 0; + if(stat(maildir, &st) < 0) + return 0; + numfiles = st.st_size / sizeof(fileheader_t); + if(numfiles <= 0) + return 0; + + /* �ݬݦ��S���H���٨SŪ�L�H�q�ɧ��^�Y�ˬd�A�IJv���� */ + if((fd = open(maildir, O_RDONLY)) > 0) { + lseek(fd, st.st_size - sizeof(fileheader_t), SEEK_SET); + while(numfiles--) { + read(fd, &my_mail, sizeof(fileheader_t)); + if(!(my_mail.filemode & FILE_READ)) { + close(fd); + return 1; + } + lseek(fd, -(off_t)2 * sizeof(fileheader_t), SEEK_CUR); + } + close(fd); + } + return 0; +} + +#ifdef EMAIL_JUSTIFY +static void mail_justify(userec_t muser) { + fileheader_t mhdr; + char title[128], buf1[80]; + FILE* fp; + + sethomepath(buf1, muser.userid); + stampfile(buf1, &mhdr); + unlink(buf1); + strcpy(mhdr.owner, cuser.userid); + strncpy(mhdr.title, "[�f�ֳq�L]", TTLEN); + mhdr.savemode = 0; + mhdr.filemode = 0; + + if(valid_ident(muser.email) && !invalidaddr(muser.email)) { + char title[80], *ptr; + unsigned short checksum; /* 16-bit is enough */ + char ch; + + checksum = searchuser(muser.userid); + ptr = muser.email; + while((ch = *ptr++)) { + if(ch <= ' ') + break; + if(ch >= 'A' && ch <= 'Z') + ch |= 0x20; + checksum = (checksum << 1) ^ ch; + } + + sprintf(title, "[PTT BBS]To %s(%d:%d) [User Justify]", + muser.userid, getuser(muser.userid) + MAGIC_KEY, checksum); + if( +#ifndef USE_BSMTP + bbs_sendmail(NULL, title, muser.email) +#else + bsmtp(NULL, title, muser.email, MQ_JUSTIFY); +#endif + < 0) + Link("etc/bademail", buf1); + else + Link("etc/replyemail", buf1); + } else + Link("etc/bademail", buf1); + sethomedir(title, muser.userid); + append_record(title, &mhdr, sizeof(mhdr)); +} +#endif /* EMAIL_JUSTIFY */ diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c new file mode 100644 index 00000000..c4849da5 --- /dev/null +++ b/mbbsd/mbbsd.c @@ -0,0 +1,1465 @@ +/* $Id: mbbsd.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <setjmp.h> +#include <signal.h> +#include <unistd.h> +#include <fcntl.h> +#include <syslog.h> +#include <errno.h> +#include <netdb.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/telnet.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" +#ifdef FreeBSD + #include <machine/limits.h> +#else + #include <limits.h> +#endif + +#define SOCKET_QLEN 4 +#define TH_LOW 100 +#define TH_HIGH 120 + +extern int t_lines, t_columns; /* Screen size / width */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern userinfo_t *currutmp; +extern int curr_idle_timeout; + +static void do_aloha (char *hello); + +static jmp_buf byebye; + +int talkrequest = NA; + +static char remoteusername[40] = "?"; + +extern struct fromcache_t *fcache; +extern struct utmpfile_t *utmpshm; +extern int fcache_semid; + +static unsigned char enter_uflag; +static int use_shell_login_mode = 0; + +char fromhost[STRLEN] = "\0"; + +static struct sockaddr_in xsin; + +/* 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 () +{ + int n; + char buf[80]; + + /* + * 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); + + strftime (buf, 80, "%d/%b/%Y:%H:%M:%S", dummy_time); + + if ((n = fork ())){ + exit (0); + } + + /* rocker.011018: it's a good idea to close all unexcept fd!! */ + n = getdtablesize (); + while (n) + close (--n); + /* 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 */ + if ((n = fork ())){ + exit (0); + } +} + +static void +reapchild (int sig) +{ + int state, pid; + + while ((pid = waitpid (-1, &state, WNOHANG | WUNTRACED)) > 0) + ; +} + +#define BANNER \ +"�i" BBSNAME "�j�� �x�j�y��� ��(" MYHOSTNAME ") �մT(" MYIP ") " +/* +#define BANNER \ +"�i" BBSNAME "�j�� �x�j�y��� ��(" MYHOSTNAME ")\r\n"\ +" �մT(" MYIP ") " +*/ +/* check load and print approriate banner string in buf */ +static int +chkload (char *buf) +{ + char cpu_load[30]; + int i; + + i = cpuload (cpu_load); + + sprintf (buf, BANNER" �t�έt��\r\n %s %s \r\n", cpu_load, + (i > MAX_CPULOAD ? "�A���t���q�A�еy��A�� " + "(�ЧQ��port 3000~3010�s�u)" : "")); +#ifdef INSCREEN + strcpy(buf, (i > MAX_CPULOAD ? BANNER + "���t���q�A�еy��A��(�ЧQ��port 3000~3010�s�u)" : "")); +#else + sprintf(buf, BANNER "%s\r\n", + (i > MAX_CPULOAD ? "���t���q�A�еy��A��(�ЧQ��port 3000~3010�s�u)":"")); +#endif + if (i > MAX_CPULOAD) + return 1; + else if (i > MAX_CPULOAD / 2) + curr_idle_timeout = 10 * 60; + else + curr_idle_timeout = 30 * 60; + + return 0; +} + +extern userec_t cuser; + +void +log_user (char *msg) +{ + char filename[200]; + + sprintf (filename, BBSHOME "/home/%c/%s/USERLOG", + cuser.userid[0], cuser.userid); + log_file (filename, msg); +} + +extern time_t login_start_time; + +void +log_usies (char *mode, char *mesg) +{ + char genbuf[200]; + time_t now = time (0); + + if (!mesg) + sprintf (genbuf, cuser.userid[0] ? "%s %s %-12s Stay:%d (%s)" : + "%s %s %s Stay:%d (%s)", + Cdate (&now), mode, cuser.userid, + (int)(now - login_start_time) / 60, cuser.username); + else + sprintf (genbuf, cuser.userid[0] ? "%s %s %-12s %s" : "%s %s %s%s", + Cdate (&now), mode, cuser.userid, mesg); + log_file (FN_USIES, genbuf); + + /* �l�ܨϥΪ� */ + if (HAS_PERM (PERM_LOGUSER)) + log_user (genbuf); +} + +static void +setflags (int mask, int value) +{ + if (value) + cuser.uflag |= mask; + else + cuser.uflag &= ~mask; +} + +extern int usernum; +extern int currmode; + +void +u_exit (char *mode) +{ + //userec_t xuser; + int diff = (time (0) - login_start_time) / 60; + + reload_money(); + auto_backup (); + save_brdbuf(); + setflags (PAGER_FLAG, currutmp->pager != 1); + setflags (CLOAK_FLAG, currutmp->invisible); + + cuser.invisible = currutmp->invisible; + cuser.pager = currutmp->pager; + cuser.mind = currutmp->mind; + if (!(HAS_PERM (PERM_SYSOP) && HAS_PERM (PERM_DENYPOST)) && + !currutmp->invisible ) + do_aloha ("<<�U���q��>> -- �ڨ��o�I"); + + purge_utmp (currutmp); + if ((cuser.uflag != enter_uflag) || (currmode & MODE_DIRTY) || diff) + { + if (!diff && cuser.numlogins) + cuser.numlogins = --cuser.numlogins; + /* Leeym �W�����d�ɶ���� */ + } + passwd_update (usernum, &cuser); + log_usies (mode, NULL); +} + +static void +system_abort () +{ + if (currmode) + u_exit ("ABORT"); + + clear (); + refresh (); + fprintf (stdout, "���¥��{, �O�o�`�ӳ� !\n"); + exit (0); +} + +void +abort_bbs (int sig) +{ + if (currmode) + u_exit ("AXXED"); + exit (0); +} + +static void +abort_bbs_debug (int sig) +{ + static int reentrant = 0; + + if (!reentrant){ + reentrant = 1; + if (currmode) + u_exit ("AXXED"); + setproctitle("debug me!(%d)",sig); + sleep(3600); /* wait 60 mins for debug */ + } + exit (0); +} + +/* �n�� BBS �{�� */ +static void +mysrand () +{ + srand (time (NULL) + currutmp->pid); /* �ɶ��� pid �� rand �� seed */ +} + +extern userec_t xuser; + +int +dosearchuser (char *userid) +{ + if ((usernum = getuser (userid))) + memcpy (&cuser, &xuser, sizeof (cuser)); + else + memset (&cuser, 0, sizeof (cuser)); + return usernum; +} + +static void +talk_request () +{ + bell (); + bell (); + if (currutmp->msgcount){ + char buf[200]; + time_t now = time (0); + + sprintf (buf, "\033[33;41m��%s\033[34;47m [%s] %s \033[0m", + utmpshm->uinfo[currutmp->destuip].userid, my_ctime (&now), + (currutmp->sig == 2)? "���n�����s���I(��Ctrl-U,l�d�ݼ��T�O��)" + : "�I�s�B�I�s�Ať��Ц^��"); + move (0, 0); + clrtoeol (); + outs (buf); + refresh (); + } + else{ + unsigned char mode0 = currutmp->mode; + char c0 = currutmp->chatid[0]; + screenline_t *screen0 = calloc (t_lines, sizeof (screenline_t)); + extern screenline_t *big_picture; + + currutmp->mode = 0; + currutmp->chatid[0] = 1; + memcpy (screen0, big_picture, t_lines * sizeof (screenline_t)); + talkreply (); + currutmp->mode = mode0; + currutmp->chatid[0] = c0; + memcpy (big_picture, screen0, t_lines * sizeof (screenline_t)); + free (screen0); + redoscr (); + } +} + +extern char *fn_writelog; +FILE *fp_writelog = NULL; + +void +show_last_call_in (int save) +{ + char buf[200]; + sprintf (buf, "\033[1;33;46m��%s\033[37;45m %s \033[m", + currutmp->msgs[0].userid, currutmp->msgs[0].last_call_in); + move (b_lines, 0); + clrtoeol (); + refresh (); + outmsg (buf); + + if (save){ + char genbuf[200]; + time_t now; + if (!fp_writelog){ + sethomefile (genbuf, cuser.userid, fn_writelog); + fp_writelog = fopen (genbuf, "a"); + } + if (fp_writelog){ + time (&now); + fprintf (fp_writelog, "%s \033[0m[%s]\n", buf, Cdatelite (&now)); + } + } +} + +extern unsigned int currstat; +water_t water[6], *swater[6], *water_which=&water[0]; +char water_usies=0; +extern int watermode; +static int add_history_water(water_t *w, 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(msgque_t *msg) +{ + int i,j; + water_t *tmp; + add_history_water(&water[0], msg); + for(i = 0 ; i < 5 && swater[i] ; i++ ) + if( swater[i]->pid == msg->pid ) + break; + if( i != 5 ){ + if( !swater[i] ){ + water_usies = i + 1; + swater[i] = &water[i + 1]; + strcpy(swater[i]->userid, msg->userid); + swater[i]->pid = msg->pid; + } + tmp = swater[i]; + } + else{ + tmp = swater[4]; + memset(swater[4], 0, sizeof (water_t)); + strcpy(swater[4]->userid, msg->userid); + swater[4]->pid = msg->pid; + i = 4; + } + + 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; +} + +static void +write_request (int sig) +{ + struct tm *ptime; + time_t now; + + time (&now); + ptime = localtime (&now); + + if (currutmp->pager != 0 && + 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) + { + int i; + char c0 = currutmp->chatid[0]; + int currstat0 = currstat; + unsigned char mode0 = currutmp->mode; + + currutmp->mode = 0; + currutmp->chatid[0] = 2; + currstat = XMODE; + + do + { + bell (); + show_last_call_in (1); + igetch (); + currutmp->msgcount--; + if (currutmp->msgcount >= MAX_MSGS) + { + /* this causes chaos... jochang */ + raise (SIGFPE); + } + + add_history(&currutmp->msgs[0]); + for (i = 0; i < currutmp->msgcount; i++) + currutmp->msgs[i] = currutmp->msgs[i + 1]; + } + while (currutmp->msgcount); + currutmp->chatid[0] = c0; + currutmp->mode = mode0; + currstat = currstat0; + } + else + { + bell (); + show_last_call_in (1); + add_history(&currutmp->msgs[0]); + + refresh (); + currutmp->msgcount = 0; + } +} + +#if 0 +static void +write_request (int sig) +{ + int i, mtimemin, wu; + static char inlock = 0; + if( inlock ) /* �p�G�w�g�i�ӤF (���ܤW�Ӥ��y�٨S���B�z��, + �s�����y�S�i��) �h��������ƪ��� return */ + return; + inlock = 1; + do{ + for( wu = 0 ; wu < 5 ; ++wu ) + if( water[wu].pid == currutmp->msgs[0].pid ) + break; + if( wu == 5 ){ + for( i = 0, mtimemin = INT_MAX ; i < 5 ; ++i ) + if( water[i].pid == 0 ){ + ++water_usies; + wu = i; + break; + } + else if( water[i].mtime < mtimemin ){ + mtimemin = water[i].mtime; + wu = i; + } + water[wu].pid = currutmp->msgs[0].pid; + strcpy(water[wu].userid, currutmp->msgs[0].userid); + water[wu].msgtop = 0; + for( i = 0 ; i < 5 ; ++i ) + water[wu].msg[i][0] = 0; + } + water[wu].mtime = time(NULL); + strncpy(water[wu].msg[ (int)water[wu].msgtop ], + currutmp->msgs[0].last_call_in, 64); + ++water[wu].msgtop; + water[wu].msgtop %= 5; + + bell (); + show_last_call_in (1); + refresh(); + + if( watermode == 0 ){ /* in waterball selection mode + if( wu != 0 ){ + water_scr(water_which, 0); + qsort(water, 5, sizeof(water_t), cmpwatermtime); + for( i = 0 ; i < 5 ; ++i ) + if( water[i].pid == 0 ) + break; + else + water_scr(i, 0); + water_scr(water_which = 0, 1); + refresh(); + } */ + } + --currutmp->msgcount; + for( i = 0 ; i < currutmp->msgcount - 1 ; ++i ) + currutmp->msgs[i] = currutmp->msgs[i + 1]; + } while( currutmp->msgcount > 0 ); + inlock = 0; +} +#endif + +static void +multi_user_check () +{ + register userinfo_t *ui; + register pid_t pid; + char genbuf[3]; + + if (HAS_PERM (PERM_SYSOP)) + return; /* don't check sysops */ + + if (cuser.userlevel){ + if (!(ui = (userinfo_t *) search_ulist (usernum))) + return; /* user isn't logged in */ + + pid = ui->pid; + if (!pid /*|| (kill(pid, 0) == -1) */ ) + return; /* stale entry in utmp file */ + + getdata (b_lines - 1, 0, "�z�Q�R����L���ƪ� login (Y/N)�ܡH[Y] ", + genbuf, 3, LCECHO); + + if (genbuf[0] != 'n'){ + if (pid > 0) + kill (pid, SIGHUP); + log_usies ("KICK ", cuser.username); + } + else{ + if (search_ulistn(usernum, 3)!=NULL) + system_abort (); /* Goodbye(); */ + } + } + else{ + /* allow multiple guest user */ + if (search_ulistn(usernum, 100)!=NULL){ + outs ("\n��p�A�ثe�w���Ӧh guest, �еy��A�աC\n"); + pressanykey (); + oflush (); + exit (1); + } + } +} + +/* bad login */ +static char str_badlogin[] = "logins.bad"; + +static void +logattempt (char *uid, char type) +{ + char fname[40]; + int fd, len; + char genbuf[200]; + + sprintf (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 == '-'){ + sprintf (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); + } + } +} + +extern char *str_new; +extern char *err_uid; + +static void +login_query () +{ + char uid[IDLEN + 1], passbuf[PASSLEN]; + int attempts; + char genbuf[200]; + extern struct utmpfile_t *utmpshm; + resolve_utmp (); + attach_uhash (); + attempts = utmpshm->number; + show_file ("etc/Welcome", 1, -1, NO_RELOAD); + output ("1", 1); + if (attempts >= MAX_ACTIVE){ + outs ("�ѩ�H�ƤӦh�A�бz�y��A�ӡC\n"); + refresh (); + exit (1); + } + + /* hint */ + + attempts = 0; + while (1){ + if (attempts++ >= LOGINATTEMPTS){ + more ("etc/goodbye", NA); + pressanykey (); + exit (1); + } + getdata (20, 0, "�п�J�N���A�ΥH[guest]���[�A�H[new]���U�G", + uid, IDLEN + 1, DOECHO); + if (strcasecmp (uid, str_new) == 0){ +#ifdef LOGINASNEW + new_register (); + break; +#else + outs ("���t�Υثe�L�k�H new ���U, �Х� guest �i�J\n"); + continue; +#endif + } + else if (uid[0] == '\0' || !dosearchuser (uid)){ + outs (err_uid); + } + else if (strcmp (uid, STR_GUEST)){ + getdata (21, 0, MSG_PASSWD, passbuf, PASSLEN, NOECHO); + passbuf[8] = '\0'; + + if (!checkpasswd (cuser.passwd, passbuf) + /* || (HAS_PERM(PERM_SYSOP) && !use_shell_login_mode) */ ){ + logattempt (cuser.userid, '-'); + outs (ERR_PASSWD); + } + else{ + logattempt (cuser.userid, ' '); + if (strcasecmp ("SYSOP", cuser.userid) == 0) + cuser.userlevel = PERM_BASIC | PERM_CHAT | PERM_PAGE | + PERM_POST | PERM_LOGINOK | PERM_MAILLIMIT | + PERM_CLOAK | PERM_SEECLOAK | PERM_XEMPT | + PERM_DENYPOST | PERM_BM | PERM_ACCOUNTS | + PERM_CHATROOM | PERM_BOARD | PERM_SYSOP | PERM_BBSADM; + break; + } + } + else{ /* guest */ + cuser.userlevel = 0; + cuser.uflag = COLOR_FLAG | PAGER_FLAG | BRDSORT_FLAG | MOVIE_FLAG; + break; + } + } + multi_user_check (); + sethomepath (genbuf, cuser.userid); + mkdir (genbuf, 0755); +} + +void +add_distinct (char *fname, char *line) +{ + FILE *fp; + int n = 0; + + if ((fp = fopen (fname, "a+"))){ + char buffer[80]; + char tmpname[100]; + FILE *fptmp; + + strcpy (tmpname, fname); + 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); + unlink (fname); + rename (tmpname, fname); + } +} + +void +del_distinct (char *fname, char *line) +{ + FILE *fp; + int n = 0; + + if ((fp = fopen (fname, "r"))){ + char buffer[80]; + char tmpname[100]; + FILE *fptmp; + + strcpy (tmpname, fname); + 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)) + 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); + unlink (fname); + rename (tmpname, fname); + } +} + +#ifdef WHERE +static int +where (char *from) +{ + register int i = 0, count = 0, j; + + for (j = 0; j < fcache->top; j++){ + char *token = strtok (fcache->domain[j], "&"); + + i = 0; + count = 0; + while (token){ + if (strstr (from, token)) + count++; + token = strtok (NULL, "&"); + i++; + } + if (i == count) + break; + } + if (i != count) + return 0; + return j; +} +#endif + +static void +check_BM () +{ + int i; + boardheader_t *bhdr; + extern boardheader_t *bcache; + extern int numboards; + + cuser.userlevel &= ~PERM_BM; + for (i = 0, bhdr = bcache; i < numboards && !is_BM (bhdr->BM); i++, bhdr++) + ; +} + +extern pid_t currpid; +extern crosspost_t postrecord; + +static void +setup_utmp (int mode) +{ + userinfo_t uinfo; + /* + char buf[80]; + char remotebuf[1024]; + time_t now = time(NULL); + */ + memset (&uinfo, 0, sizeof (uinfo)); + uinfo.pid = currpid = getpid (); + uinfo.uid = usernum; + uinfo.mode = currstat = mode; + uinfo.msgcount = 0; + uinfo.mailalert = load_mailalert (cuser.userid); + if (!(cuser.numlogins % 20) && cuser.userlevel & PERM_BM) + check_BM (); /* Ptt �۰ʨ��U��¾�O�D�v�O */ + + uinfo.userlevel = cuser.userlevel; + uinfo.sex = cuser.sex % 8; + uinfo.lastact = time (NULL); + + postrecord.times = 0; /* �p��crosspost�� */ + + strcpy (uinfo.userid, cuser.userid); + strcpy (uinfo.realname, cuser.realname); + strcpy (uinfo.username, cuser.username); + strncpy (uinfo.from, fromhost, 23); + + uinfo.five_win = cuser.five_win; + uinfo.five_lose = cuser.five_lose; + uinfo.five_tie = cuser.five_tie; + + uinfo.invisible = cuser.invisible % 2; + uinfo.pager = cuser.pager%5; + uinfo.mind = cuser.mind; + uinfo.brc_id = 0; +#ifdef WHERE + uinfo.from_alias = where (fromhost); +#else + uinfo.from_alias = 0; +#endif +#ifndef FAST_LOGIN + setuserfile (buf, "remoteuser"); + + strcpy (remotebuf, fromhost); + strcat (remotebuf, ctime (&now)); + remotebuf[strlen (remotebuf) - 1] = 0; + add_distinct (buf, remotebuf); +#endif + if (enter_uflag & CLOAK_FLAG) + uinfo.invisible = YEA; + getnewutmpent (&uinfo); +#ifndef _BBS_UTIL_C_ + friend_load (); +#endif +} + +extern char margs[]; +extern char *str_sysop; +extern char *loginview_file[NUMVIEWFILE][2]; + +static void +user_login () +{ + char ans[4], i; + char genbuf[200]; + struct tm *ptime, *tmp; + time_t now; + int a; + /*** Heat:�s�i�� + char *ADV[] = { + "7/17 @LIVE �üu, ��Y�J �� �J�����n�e�� ptt ���R�Ϊ�!", + "�����Ա��Ь� PttAct �O!!", + }; ***/ + + log_usies ("ENTER", fromhost); + setproctitle ("%s: %s", margs, cuser.userid); + resolve_garbage (); + resolve_fcache (); + resolve_boards (); + memset( &water[0],0,sizeof(water_t) * 6); + strcpy(water[0].userid, " ���� "); + /* ��l�� uinfo�Bflag�Bmode */ + setup_utmp (LOGIN); + mysrand (); /* ��l��: random number �W�[user��ɶ����t�� */ + currmode = MODE_STARTED; + enter_uflag = cuser.uflag; + + /* get local time */ + time (&now); + ptime = localtime (&now); + tmp = localtime (&cuser.lastlogin); + if ((a = utmpshm->number) > fcache->max_user){ + fcache->max_user = a; + fcache->max_time = now; + } + init_brdbuf(); + brc_initial (DEFAULT_BOARD); + set_board (); + /* �e���B�z�}�l */ + if (!(HAS_PERM (PERM_SYSOP) && HAS_PERM (PERM_DENYPOST)) && !currutmp->invisible ) + do_aloha ("<<�W���q��>> -- �ڨӰաI"); + if (ptime->tm_mday == cuser.day && ptime->tm_mon + 1 == cuser.month){ + more ("etc/Welcome_birth", NA); + currutmp->birth = 1; + } + else{ +#ifdef MULTI_WELCOME_LOGIN + char buf[80]; + int nScreens; + for( nScreens = 0 ; nScreens < 10 ; ++nScreens ){ + sprintf(buf, "etc/Welcome_login.%d", nScreens); + if( access(buf, 0) < 0 ) + break; + } + printf("%d\n", nScreens); + if( nScreens == 0 ){ // multi screen error? + more ("etc/Welcome_login", NA); + } + else{ + sprintf(buf, "etc/Welcome_login.%d", (int)login_start_time % nScreens); + more (buf, NA); + } +#else + more ("etc/Welcome_login", NA); +#endif +// pressanykey(); +// more("etc/CSIE_Week", NA); + currutmp->birth = 0; + } + + if (cuser.userlevel){/* not guest */ + move (t_lines - 4, 0); + prints (" �w��z�� \033[1;33m%d\033[0;37m ���X�����A" + "�W���z�O�q \033[1;33m%s\033[0;37m �s�������A\n" + " �ڰO�o���ѬO \033[1;33m%s\033[0;37m�C\n", + ++cuser.numlogins, cuser.lasthost, Cdate (&cuser.lastlogin)); + pressanykey (); + + if (currutmp->birth && tmp->tm_mday != ptime->tm_mday){ + more ("etc/birth.post", YEA); + brc_initial ("WhoAmI"); + set_board (); + do_post (); + } + setuserfile (genbuf, str_badlogin); + if (more (genbuf, NA) != -1){ + getdata (b_lines - 1, 0, "�z�n�R���H�W���~���ժ��O����(Y/N)?[Y]", + ans, 3, LCECHO); + if (*ans != 'n') + unlink (genbuf); + } + check_register (); + strncpy (cuser.lasthost, fromhost, 16); + cuser.lasthost[15] = '\0'; + restore_backup (); + } + else if (!strcmp (cuser.userid, STR_GUEST)){ + 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; + sprintf (cuser.username, "����}�Ӫ�%s", nick[(int) i]); + sprintf (currutmp->username, cuser.username); + sprintf (cuser.realname, name[(int) i]); + sprintf (currutmp->realname, cuser.realname); + sprintf (cuser.address, addr[(int) i]); + cuser.sex = i % 8; + currutmp->pager = 2; + pressanykey (); + } + else + pressanykey (); + + if (!PERM_HIDE (currutmp)) + cuser.lastlogin = login_start_time; + + passwd_update (usernum, &cuser); + + for (i = 0; i < NUMVIEWFILE; i++) + if ((cuser.loginview >> i) & 1) + more (loginview_file[(int) i][0], YEA); + + +} + +static void +do_aloha (char *hello) +{ + FILE *fp; + char userid[80]; + char genbuf[200]; + + setuserfile (genbuf, "aloha"); + if ((fp = fopen (genbuf, "r"))){ + sprintf (genbuf, hello); + while (fgets (userid, 80, fp)){ + userinfo_t *uentp; + int tuid; + + if ((tuid = searchuser (userid)) && tuid != usernum && + (uentp = (userinfo_t *) search_ulist (tuid)) && + isvisible(uentp, currutmp)){ + my_write (uentp->pid, genbuf, uentp->userid, 2); + } + } + fclose (fp); + } +} + +static void +do_term_init () +{ + term_init (); + initscr (); +} + +extern char *fn_register; +extern int showansi; + +static void +start_client () +{ + extern struct commands_t cmdlist[]; +#if FORCE_PROCESS_REGISTER_FORM + int nreg; +#endif + + /* 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_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 */ + user_login (); + m_init (); + +#if FORCE_PROCESS_REGISTER_FORM + if (HAS_PERM (PERM_SYSOP) && (nreg = dashs (fn_register) / 163) > 100){ + char cpu_load[30]; + if (cpuload (cpu_load) > MAX_CPULOAD * 2 / 3) + /* DickG: �ھڥثe�� load �ӨM�w�n�f�֪��ƥ� */ + scan_register_form (fn_register, 1, nreg / 20); + else + scan_register_form (fn_register, 1, nreg / 10); + } +#endif + if (HAVE_PERM (PERM_SYSOP | PERM_BM)) + b_closepolls (); + if (!(cuser.uflag & COLOR_FLAG)) + showansi = 0; +#ifdef DOTIMEOUT + /* init_alarm(); */// cause strange logout with saving post. + signal (SIGALRM, SIG_IGN); +#else + signal (SIGALRM, SIG_IGN); +#endif + if (chkmailbox ()) + m_read (); + + domenu (MMENU, "�D�\\���", (currutmp->mailalert ? 'M' : 'C'), cmdlist); +} + +/* FSA (finite state automata) for telnet protocol */ +static void +telnet_init () +{ + static char svr[] = { + IAC, DO, TELOPT_TTYPE, + IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE, + IAC, WILL, TELOPT_ECHO, + IAC, WILL, TELOPT_SGA + }; + char *cmd; + int n, len, rset; + struct timeval to; + char buf[64]; + for (n = 0, cmd = svr; n < 4; n++){ + len = (n == 1 ? 6 : 3); + write (0, cmd, len); + cmd += len; + to.tv_sec = 3; + to.tv_usec = 0; + rset=1; + if (select (1, (fd_set *) & rset, NULL, NULL, &to) > 0) + recv(0, buf, sizeof (buf),0); + } +} + +/* ���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 STRN_CPY(d,s,l) { strncpy((d),(s),(l)); (d)[(l)-1] = 0; } +#define RFC931_TIMEOUT 10 +#define RFC931_PORT 113 /* Semi-well-known port */ +#define ANY_PORT 0 /* Any old port will do */ + +/* timeout - handle timeouts */ +static void +timeout (int sig) +{ + longjmp (byebye, sig); +} + +static void +getremotename (struct sockaddr_in *from, char *rhost, char *rname) +{ + + /* get remote host name */ + +#ifdef FAST_LOGIN + 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; + strcpy (rname, user); + } + } + alarm (0); + } + fclose (fp); +#endif +} + +static int +bind_port (int port) +{ + int sock, on; + + 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)); + + on = 0; + setsockopt (sock, SOL_SOCKET, SO_LINGER, (char *) &on, sizeof (on)); + + 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 void shell_login (int argc, char *argv[], char *envp[]); +static void daemon_login (int argc, char *argv[], char *envp[]); +static int check_ban_and_load (int fd); +#ifdef SUPPORT_GB +extern int current_font_type; +#endif + +int +main (int argc, char *argv[], char *envp[]) +{ + /* avoid SIGPIPE */ + signal (SIGPIPE, SIG_IGN); + + /* avoid erroneous signal from other mbbsd */ + signal (SIGUSR1, SIG_IGN); + signal (SIGUSR2, SIG_IGN); + + /* check if invoked as "bbs" */ + if (argc == 3) + shell_login (argc, argv, envp); + else + daemon_login (argc, argv, envp); + + return 0; +} + +static void +shell_login (int argc, char *argv[], char *envp[]) +{ + + /* Give up root privileges: no way back from here */ + setgid (BBSGID); + setuid (BBSUID); + chdir (BBSHOME); + + /* mmap passwd file */ + if (passwd_mmap ()) + exit (1); + + use_shell_login_mode = 1; + initsetproctitle (argc, argv, envp); + + /* copy fromindent: Standard input:1138: Error:Unexpected end of file + the original "bbs" */ + if (argc > 1){ + strcpy (fromhost, argv[1]); + if (argc > 3) + strcpy (remoteusername, argv[3]); + } + + close (2); + /* don't close fd 1, at least init_tty need it */ + + init_tty (); + if (check_ban_and_load (0)){ + exit (0); + } + start_client (); +} + +static void +daemon_login (int argc, char *argv[], char *envp[]) +{ + int msock, csock; /* socket for Master and Child */ + FILE *fp; + int listen_port = 23; + int len_of_sock_addr; + char buf[256]; + + /* setup standalone */ + + start_daemon(); + + signal_restart(SIGCHLD, reapchild); + + /* choose port */ + if(argc == 1) + listen_port = 3006; + else if(argc >= 2) + listen_port = atoi(argv[1]); + + sprintf(margs, "%s %d ", argv[0],listen_port); + + /* port binding */ + xsin.sin_family = AF_INET; + msock = bind_port(listen_port); + if(msock<0) { + syslog(LOG_INFO, "mbbsd bind_port failed.\n"); + exit(1); + } + + + initsetproctitle(argc, argv, envp); + setproctitle("%s: listening ", margs); + + /* Give up root privileges: no way back from here */ + setgid(BBSGID); + setuid(BBSUID); + chdir(BBSHOME); + + /* mmap passwd file */ + if(passwd_mmap()) + { + exit(1); + } + sprintf(buf, "run/mbbsd.%d.pid", listen_port); + if((fp = fopen(buf, "w"))) { + fprintf(fp, "%d\n", getpid()); + fclose(fp); + } + + /* main loop */ + for(;;) { + len_of_sock_addr = sizeof(xsin); + csock = accept(msock, (struct sockaddr *)&xsin, &len_of_sock_addr); + + if(csock < 0) { + if(errno!=EINTR) sleep(1); + continue; + } + + if(check_ban_and_load(csock)) + { + close(csock); + continue; + } + + if(fork()==0) + break; + else + close(csock); + + } + /* here is only child running */ + + setproctitle("%s: ...login wait... ", margs); + close(msock); + dup2(csock, 0); + close(csock); + + getremotename(&xsin, fromhost, remoteusername); + telnet_init(); + start_client(); + close(0); + close(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 char buf[256]; + static time_t chkload_time = 0; + static int overload = 0; /* overload or banned, update every 1 sec */ + static int banned = 0; + + if((time(0) - chkload_time) > 1) { + overload = chkload(buf); + banned = !access(BBSHOME "/BAN",R_OK) && + (strcmp(fromhost, "localhost") != 0); + chkload_time = time(0); + } + + write(fd, buf, strlen(buf)); + + if(banned && (fp = fopen(BBSHOME "/BAN", "r"))) { + while(fgets(buf, 256, fp)) + write(fd, buf, strlen(buf)); + fclose(fp); + } + + if(banned || overload) + return -1; + +#ifdef INSCREEN + write(fd, INSCREEN, strlen(INSCREEN)); +#endif + + return 0; +} diff --git a/mbbsd/menu.c b/mbbsd/menu.c new file mode 100644 index 00000000..d48670b3 --- /dev/null +++ b/mbbsd/menu.c @@ -0,0 +1,596 @@ +/* $Id: menu.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" +extern int usernum; +extern int talkrequest; +extern char *fn_register; +extern char currboard[]; /* name of currently selected board */ +extern int currmode; +extern unsigned int currstat; +extern char reset_color[]; +extern userinfo_t *currutmp; +extern char *BBSName; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ + +/* help & menu processring */ +static int refscreen = NA; +extern char *boardprefix; +extern struct utmpfile_t *utmpshm; + +int egetch() { + int rval; + + while(1) { + rval = igetkey(); + if(talkrequest) { + talkreply(); + refscreen = YEA; + return rval; + } + if(rval != Ctrl('L')) + return rval; + redoscr(); + } +} + +extern userec_t cuser; +extern char *fn_board; +extern char board_hidden_status; + +void showtitle(char *title, char *mid) { + char buf[40], numreg[50]; + int nreg, spc = 0, pad, bid; + boardheader_t bh; + static char lastboard[16] = {0}; + + spc = strlen(mid); + if(title[0] == 0) + title++; + else if(currutmp->mailalert) { + mid = "\033[41;5m �l�t�ӫ��a�o " TITLE_COLOR; + spc = 22; + } else if(HAS_PERM(PERM_SYSOP) && (nreg = dashs(fn_register)/163) > 10) { + /* �W�L�Q�ӤH���f�� */ + sprintf(numreg, "\033[41;5m ��%03d/%03d���f�� " TITLE_COLOR, + nreg, + (int)dashs("register.new.tmp") / 163); + mid = numreg; + spc = 22; + } + spc = 66 - strlen(title) - spc - strlen(currboard); + if(spc < 0) + spc = 0; + pad = 1 - (spc & 1); + memset(buf, ' ', spc >>= 1); + buf[spc] = '\0'; + + clear(); + prints(TITLE_COLOR "�i%s�j%s\033[33m%s%s%s\033[3%s�m", + title, buf, mid, buf, " " + pad, + currmode & MODE_SELECT ? "6m�t�C" : currmode & MODE_ETC ? "5m��L" : + currmode & MODE_DIGEST ? "2m��K" : "7m�ݪO"); + + if( strcmp(currboard, lastboard) ){ /* change board */ + if( currboard[0] != 0 && + (bid = getbnum(currboard)) > 0 && + (get_record(fn_board, &bh, sizeof(bh), bid) != -1) ){ + board_hidden_status = ((bh.brdattr & BRD_HIDE) && + (bh.brdattr & BRD_POSTMASK)); + strncpy(lastboard, currboard, sizeof(lastboard)); + } + } + + if( board_hidden_status ) + prints("\033[32m%s", currboard); + else + prints("%s", currboard); + prints("\033[3%dm�n\033[0m\n", currmode & MODE_SELECT ? 6 : + currmode & MODE_ETC ? 5 : currmode & MODE_DIGEST ? 2 : 7); +} + +/* �ʵe�B�z */ +#define FILMROW 11 +static unsigned char menu_row = 12; +static unsigned char menu_column = 20; +static char mystatus[160]; + +static int u_movie() { + cuser.uflag ^= MOVIE_FLAG; + return 0; +} + +void movie(int i) { + extern struct pttcache_t *ptt; + static short history[MAX_HISTORY]; + static char myweek[] = "�Ѥ@�G�T�|����"; + const char *msgs[] = {"����", "���}", "�ޱ�", "����","�n��"}; + time_t now = time(NULL); + struct tm *ptime = localtime(&now); + + if((currstat != CLASS) && (cuser.uflag & MOVIE_FLAG) && + !ptt->busystate && ptt->max_film > 0) { + if(currstat == PSALE) { + i = PSALE; + reload_money(); + } else { + do { + if(!i) + i = 1 + (int)(((float)ptt->max_film * + rand()) / (RAND_MAX + 1.0)); + + for(now = ptt->max_history; now >= 0; now--) + if(i == history[now]) { + i = 0; + break; + } + } while(i == 0); + } + + memcpy(history, &history[1], ptt->max_history * sizeof(short)); + history[ptt->max_history] = now = i; + + if(i == 999) /* Goodbye my friend */ + i = 0; + + move(1, 0); + clrtoline(1 + FILMROW); /* �M���W���� */ + Jaky_outs(ptt->notes[i], 11); /* �u�L11��N�n */ + outs(reset_color); + } + i = ptime->tm_wday << 1; + sprintf(mystatus, "\033[34;46m[%d/%d �P��%c%c %d:%02d]\033[1;33;45m%-14s" + "\033[30;47m �ثe�{�̦� \033[31m%d\033[30m�H, �ڬO\033[31m%-12s" + "\033[30m[����]\033[31m%s\033[0m", + ptime->tm_mon + 1, ptime->tm_mday, myweek[i], myweek[i + 1], + ptime->tm_hour, ptime->tm_min, currutmp->birth ? + "�ͤ�n�Ыȭ�" : ptt->today_is, + utmpshm->number, cuser.userid, msgs[currutmp->pager]); + outmsg(mystatus); + refresh(); +} + +static int show_menu(commands_t *p) { + register int n = 0; + register char *s; + const char *state[4]={"�Υ\\��", "�w�h��", "�۩w��", "SHUTUP"}; + char buf[80]; + + movie(currstat); + + move(menu_row, 0); + while((s = p[n].desc)) { + if(HAS_PERM(p[n].level)) { + sprintf(buf, s + 2, state[cuser.proverb % 4]); + prints("%*s (\033[1;36m%c\033[0m)%s\n", menu_column, "", s[1], + buf); + } + n++; + } + return n - 1; +} + +void domenu(int cmdmode, char *cmdtitle, int cmd, commands_t cmdtable[]) { + int lastcmdptr; + int n, pos, total, i; + int err; + int chkmailbox(); + static char cmd0[LOGIN]; + + if(cmd0[cmdmode]) + cmd = cmd0[cmdmode]; + + setutmpmode(cmdmode); + + showtitle(cmdtitle, BBSName); + + total = show_menu(cmdtable); + + outmsg(mystatus); + lastcmdptr = pos = 0; + + do { + i = -1; + switch(cmd) { + case Ctrl('C'): + cal(); + i = lastcmdptr; + refscreen = YEA; + break; + 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(!HAS_PERM(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(!HAS_PERM(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]; + cmd0[cmdmode] = cmdtable[lastcmdptr].desc[0]; + } + + if(cmd >= 'a' && cmd <= 'z') + cmd &= ~0x20; + while(++i <= total) + if(cmdtable[i].desc[1] == cmd) + break; + } + + if(i > total || !HAS_PERM(cmdtable[i].level)) + continue; + + if(refscreen) { + showtitle(cmdtitle, BBSName); + + show_menu(cmdtable); + + outmsg(mystatus); + refscreen = NA; + } + cursor_clear(menu_row + pos, menu_column); + n = pos = -1; + while(++n <= (lastcmdptr = i)) + if(HAS_PERM(cmdtable[n].level)) + pos++; + + cursor_show(menu_row + pos, menu_column); + } while(((cmd = egetch()) != EOF) || refscreen); + + abort_bbs(0); +} +/* INDENT OFF */ + +/* administrator's maintain menu */ +static commands_t adminlist[] = { + {m_user, PERM_ACCOUNTS, "UUser �ϥΪ̸��"}, + {search_user_bypwd, PERM_SYSOP, "SSearch User �S���j�M�ϥΪ�"}, + {search_user_bybakpwd,PERM_SYSOP, "OOld User data �d�\\�ƥ��ϥΪ̸��"}, + {m_board, PERM_SYSOP, "BBoard �]�w�ݪO"}, + {m_register, PERM_SYSOP, "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 ���]��"}, +#ifdef HAVE_MAILCLEAN + {m_mclean, PERM_SYSOP, "MMail Clean �M�z�ϥΪ̭ӤH�H�c"}, +#endif +#ifdef HAVE_REPORT + {m_trace, PERM_SYSOP, "TTrace �]�w�O�_�O��������T"}, +#endif + {NULL, 0, NULL} +}; + +/* mail menu */ +static commands_t maillist[] = { + {m_new, PERM_READMAIL, "RNew �\\Ū�s�i�l��"}, + {m_read, PERM_READMAIL, "RRead �h�\\��Ū�H���"}, + {m_send, PERM_BASIC, "RSend �����H�H"}, + {main_bbcall, PERM_LOGINOK, "BBBcall \033[1;31m�q�ܯ���\033[m"}, + {x_love, PERM_LOGINOK, "PPaper \033[1;32m���Ѳ��;�\033[m "}, + {mail_list, PERM_BASIC, "RMail List �s�ձH�H"}, + {setforward, PERM_LOGINOK,"FForward \033[32m�]�w�H�c�۰���H\033[m"}, + {m_sysop, 0, "YYes, sir! �ԴA����"}, + {m_internet, PERM_INTERNET, "RInternet �H�H�� Internet"}, + {mail_mbox, PERM_INTERNET, "RZip UserHome ��Ҧ��p�H��ƥ��]�^�h"}, + {built_mail_index, PERM_LOGINOK, "SSavemail ��H��Ϧ^��"}, + {mail_all, PERM_SYSOP, "RAll �H�H���Ҧ��ϥΪ�"}, + {NULL, 0, NULL} +}; + +/* Talk menu */ +static 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��"}, + {t_talk, PERM_PAGE, "TTalk ��H���"}, + {t_chat, PERM_CHAT, "CChat ��a���{����h"}, +#ifdef HAVE_MUD + {x_mud, 0, "VVrChat \033[1;32m������~��Ѽs��\033[m"}, +#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 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��"}, +#ifdef POSTNOTIFY + {t_post,PERM_LOGINOK, "NNewPost �s�峹�q���W��"}, +#endif + {t_special,PERM_LOGINOK, "SSpecial ��L�S�O�W��"}, + {NULL, 0, NULL} +}; + +/* User menu */ +static commands_t userlist[] = { + {u_info, PERM_LOGINOK, "IInfo �]�w�ӤH��ƻP�K�X"}, + {calendar, PERM_LOGINOK, "CCalendar �ӤH��ƾ�"}, + {u_editcalendar, PERM_LOGINOK, "CCalendarEdit �s��ӤH��ƾ�"}, + {u_loginview, PERM_LOGINOK, "LLogin View ��ܶi���e��"}, + {u_ansi, 0, "AANSI ���� ANSI \033[36m�m\033[35m��\033[37m/" + "\033[30;47m��\033[1;37m��\033[m�ҥ�"}, + {u_movie, 0, "MMovie �����ʵe�ҥ�"}, +#ifdef HAVE_SUICIDE + {u_kill, PERM_BASIC, "IKill �۱��I�I"}, +#endif + {u_editplan, PERM_LOGINOK, "QQueryEdit �s��W����"}, + {u_editsig, PERM_LOGINOK, "SSignature �s��ñ�W��"}, +#if HAVE_FREECLOAK + {u_cloak, PERM_LOGINOK, "CCloak �����N"}, +#else + {u_cloak, PERM_CLOAK, "CCloak �����N"}, +#endif + {u_register, PERM_BASIC, "RRegister ��g�m���U�ӽг�n"}, + {u_list, PERM_SYSOP, "UUsers �C�X���U�W��"}, + {NULL, 0, NULL} +}; + +/* XYZ tool menu */ +static commands_t xyzlist[] = { +#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�ݪ���ذϱƦ�]�n"}, +// {x_boards,0, "HHot Boards �m�ݪ��H��Ʀ�]�n"}, + {x_history, 0, "HHistory �m�ڭ̪������n"}, + {x_note, 0, "NNote �m�IJ��W���y�����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"}, + {x_birth, 0, "BBirthday �m����جP�j�[�n"}, + {p_sysinfo, 0, "XXload �m�d�ݨt�έt���n"}, + {NULL, 0, NULL} +}; + +/* Ptt money menu */ +static 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 int p_money() { + domenu(PSALE, "��tt�q�c��", '0', moneylist); + return 0; +}; + +static commands_t jceelist[] = { + {x_90,PERM_LOGINOK, "0090 JCEE �i90�Ǧ~�פj���p�۬d�]�t�Ρj"}, + {x_89,PERM_LOGINOK, "1189 JCEE �i89�Ǧ~�פj���p�۬d�]�t�Ρj"}, + {x_88,PERM_LOGINOK, "2288 JCEE �i88�Ǧ~�פj���p�۬d�]�t�Ρj"}, + {x_87,PERM_LOGINOK, "3387 JCEE �i87�Ǧ~�פj���p�۬d�]�t�Ρj"}, + {x_86,PERM_LOGINOK, "4486 JCEE �i86�Ǧ~�פj���p�۬d�]�t�Ρj"}, + {NULL, 0, NULL} +}; + +static int m_jcee() { + domenu(JCEE, "��tt�d�]�t��", '0', jceelist); + return 0; +} + +static int forsearch(); +static int playground(); + +/* Ptt Play menu */ +static commands_t playlist[] = { +#if HAVE_JCEE + {m_jcee, PERM_LOGINOK, "JJCEE �i �j���p�Ҭd�]�t�� �j"}, +#endif + {note, PERM_LOGINOK, "NNote �i ���y���� �j"}, + {x_weather,0 , "WWeather �i ��H�w�� �j"}, + {x_stock,0 , "SStock �i �ѥ��污 �j"}, +#ifdef HAVE_BIG2 + {x_big2, 0, "BBig2 �i �����j�ѤG �j"}, +#endif +#ifdef HAVE_MJ + {x_mj, PERM_LOGINOK, "QQkmj �i �������±N �j"}, +#endif +#ifdef HAVE_BRIDGE + {x_bridge, PERM_LOGINOK, "OOkBridge �i ���P�v�� �j"}, +#endif +#ifdef HAVE_GOPHER + {x_gopher, PERM_LOGINOK, "GGopher �i �a����Ʈw �j"}, +#endif +#ifdef HAVE_TIN + {x_tin, PERM_LOGINOK, "NNEWS �i ���ڷs�D �j"}, +#endif +#ifdef BBSDOORS + {x_bbsnet, PERM_LOGINOK, "BBBSNet �i ��L BBS�� �j"}, +#endif +#ifdef HAVE_WWW + {x_www, PERM_LOGINOK, "WWWW Browser �i �L�L�L �j"}, +#endif + {forsearch,PERM_LOGINOK, "SSearchEngine�i\033[1;35m ��tt�j�M�� \033[m�j"}, + {topsong,PERM_LOGINOK, "TTop Songs �i\033[1;32m�ڮ��I�q�Ʀ�]\033[m�j"}, + {p_money,PERM_LOGINOK, "PPay �i\033[1;31m ��tt�q�c�� \033[m�j"}, + {chicken_main,PERM_LOGINOK, "CChicken " + "�i\033[1;34m ��tt�i���� \033[m�j"}, + {playground,PERM_LOGINOK, "AAmusement �i\033[1;33m ��tt�C�ֳ� \033[m�j"}, + {NULL, 0, NULL} +}; + +static commands_t plist[] = { + +/* {p_ticket_main, PERM_LOGINOK,"00Pre �i �`�ξ� �j"}, + {alive, PERM_LOGINOK, "00Alive �i �q���� �j"}, +*/ + {ticket_main, PERM_LOGINOK, "11Gamble �i ��tt��� �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(AMUSE, "��tt�C�ֳ�",'1',plist); + return 0; +} + +static commands_t slist[] = { + {x_dict,0, "11Dictionary " + "�i\033[1;33m ����j�r�� \033[m�j"}, + {main_railway, PERM_LOGINOK, "33Railway " + "�i\033[1;32m �������d�� \033[m�j"}, + {NULL, 0, NULL} +}; + +static int forsearch() { + domenu(SREG, "��tt�j�M��", '1', slist); + return 0; +} + +/* main menu */ + +static int admin() { + domenu(ADMIN, "�t�κ��@", 'X', adminlist); + return 0; +} + +static int Mail() { + domenu(MAIL, "�q�l�l��", 'R', maillist); + return 0; +} + +static int Talk() { + domenu(TMENU, "��ѻ���", 'U', talklist); + return 0; +} + +static int User() { + domenu(UMENU, "�ӤH�]�w", 'A', userlist); + return 0; +} + +static int Xyz() { + domenu(XMENU, "�u��{��", 'M', xyzlist); + return 0; +} + +static int Play_Play() { + domenu(PMENU, "�����C�ֳ�", 'A', playlist); + return 0; +} + +static int Name_Menu() { + domenu(NMENU, "�զ⮣��", 'O', namelist); + return 0; +} + +commands_t cmdlist[] = { + {admin,PERM_SYSOP|PERM_VIEWSYSOP, "00Admin �i �t�κ��@�� �j"}, + {Announce, 0, "AAnnounce �i ��ؤ��G�� �j"}, + {Boards, 0, "FFavorite �i �� �� �̷R �j"}, + {root_board, 0, "CClass �i ���հQ�װ� �j"}, + {Mail, PERM_BASIC, "MMail �i �p�H�H��� �j"}, + {Talk, 0, "TTalk �i ��Ѱ� �j"}, + {User, 0, "UUser �i �ӤH�]�w�� �j"}, + {Xyz, 0, "XXyz �i �t�Τu��� �j"}, + {Play_Play,0, "PPlay �i �C�ֳ�/�j�Ǭd�]�j"}, + {Name_Menu,PERM_LOGINOK, "NNamelist �i �s�S�O�W�� �j"}, + {Goodbye, 0, "GGoodbye ���}�A�A���K�K"}, + {NULL, 0, NULL} +}; diff --git a/mbbsd/more.c b/mbbsd/more.c new file mode 100644 index 00000000..f7755874 --- /dev/null +++ b/mbbsd/more.c @@ -0,0 +1,931 @@ +/* $Id: more.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "perm.h" +#include "proto.h" + +extern int showansi; +extern int t_lines, t_columns; /* Screen size / width */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char *str_author1; +extern char *str_author2; +extern char *str_post1; +extern char *str_post2; +extern char *msg_seperator; +extern char reset_color[]; + +#define MORE_BUFSIZE 4096 +#define MORE_WINSIZE 4096 +#define STR_ANSICODE "[0123456789;," + +static int more_base, more_size, more_head; +static unsigned char more_pool[MORE_BUFSIZE]; + + +#define MAXPATHLEN 256 +static char *more_help[] = { + "\0�\\Ū�峹�\\����ϥλ���", + "\01��в��ʥ\\����", + "(��) �W���@��", + "(��)(Enter) �U���@��", + "(^B)(PgUp)(BackSpace) �W���@��", + "(��)(PgDn)(Space) �U���@��", + "(0)(g)(Home) �ɮ}�Y", + "($)(G) (End) �ɮ���", + "\01��L�\\����", + "(/) �j�M�r��", + "(n/N) ���ƥ�/�ϦV�j�M", + "(TAB) URL�s��", + "(Ctrl-T) �s��Ȧs��", + "(:/f/b) ���ܬY��/�U/�W�g", + "(F/B) ���ܦP�@�j�M�D�D�U/�W�g", + "(a/A) ���ܦP�@�@�̤U/�W�g", + "([/]) �D�D���\\Ū �W/�U", + "(t) �D�D���`�Ǿ\\Ū", + "(Ctrl-C) �p�p���", + "(q)(��) ����", + "(h)(H)(?) ���U�����e��", + NULL +}; + +int beep = 0; + +static void +more_goto (int fd, off_t off) +{ + int base = more_base; + + if (off < base || off >= base + more_size) + { + more_base = base = off & (-MORE_WINSIZE); + lseek (fd, base, SEEK_SET); + more_size = read (fd, more_pool, MORE_BUFSIZE); + } + more_head = off - base; +} + +static int +more_readln (int fd, unsigned char *buf) +{ + int ch; + + unsigned char *data, *tail, *cc; + int len, bytes, in_ansi; + int size, head, ansilen; + + len = bytes = in_ansi = ansilen = 0; + tail = buf + ANSILINELEN - 1; + size = more_size; + head = more_head; + data = &more_pool[head]; + + do + { + if (head >= size) + { + more_base += size; + data = more_pool; + more_size = size = read (fd, data, MORE_BUFSIZE); + if (size == 0) + break; + head = 0; + } + + ch = *data++; + head++; + bytes++; + if (ch == '\n') + { + break; + } + if (ch == '\t') + { + do + { + *buf++ = ' '; + } + while ((++len & 7) && len < 80); + } + else if (ch == '\033') + { + if (atoi (data + 1) > 47) + { + if ((cc = strchr (data + 1, 'm')) != NULL) + { + ch = cc - data + 1; + + data += ch; + head += ch; + bytes += ch; + } + } + else + { + if (showansi) + *buf++ = ch; + in_ansi = 1; + } + } + else if (in_ansi) + { + if (showansi) + *buf++ = ch; + if (!strchr (STR_ANSICODE, ch)) + in_ansi = 0; + } + else if (isprint2 (ch)) + { + len++; + *buf++ = ch; + } + } + while (len < 80 && buf < tail); + *buf = '\0'; + more_head = head; + return bytes; +} + +/* not used +static int readln(FILE *fp, char *buf) { + register int ch, i, len, bytes, in_ansi; + + len = bytes = in_ansi = i = 0; + while(len < 80 && i < ANSILINELEN && (ch = getc(fp)) != EOF) { + bytes++; + if(ch == '\n') + break; + else if(ch == '\t') + do { + buf[i++] = ' '; + } while((++len & 7) && len < 80); + else if(ch == '\a') + beep = 1; + else if(ch == '\033') { + if(showansi) + buf[i++] = ch; + in_ansi = 1; + } else if(in_ansi) { + if(showansi) + buf[i++] = ch; + if(!strchr("[0123456789;,", ch)) + in_ansi = 0; + } else if(isprint2(ch)) { + len++; + buf[i++] = ch; + } + } + buf[i] = '\0'; + return bytes; +} +*/ + +extern userec_t cuser; + +static int more_web(char *fpath, int promptend); + +int more(char *fpath, int promptend) { + extern char* strcasestr(); + static char *head[4] = {"�@��", "���D", "�ɶ�" ,"��H"}; + char *ptr, *word = NULL, buf[ANSILINELEN + 1], *ch1; + struct stat st; + +/* rocker */ + //FILE *fp; + int fd, fsize; + + unsigned int pagebreak[MAX_PAGES], pageno, lino = 0; + int line, ch, viewed, pos, numbytes; + int header = 0; + int local = 0; + char search_char0=0; + static char search_str[81]=""; + typedef char* (*FPTR)(); + static FPTR fptr; + int searching = 0; + int scrollup = 0; + char *printcolor[3]= {"44","33;45","0;34;46"}, color =0; + char *http[80]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; + /* Ptt */ + char pagemode = 0; + char pagecount = 0; + + memset(pagebreak, 0, sizeof(pagebreak)); + if(*search_str) + search_char0 = *search_str; + *search_str = 0; + + + fd = open (fpath, O_RDONLY, 0600); + if (fd < 0) return -1; + + if(fstat(fd, &st) || ((fsize = st.st_size) <= 0) || S_ISDIR (st.st_mode)) + { + close(fd); //Ptt + return -1; + } + pagebreak[0] = pageno = viewed = line = pos = 0; + clear(); + +/* rocker */ + + more_base = more_head = more_size = 0; + + while((numbytes = more_readln(fd, buf)) || (line == t_lines)) { + if(scrollup) { + rscroll(); + move(0, 0); + } + if(numbytes) { /* �@���ƳB�z */ + if(!viewed) { /* begin of file */ + if(showansi) { /* header processing */ + if(!strncmp(buf, str_author1, LEN_AUTHOR1)) { + line = 3; + word = buf + LEN_AUTHOR1; + local = 1; + } else if(!strncmp(buf, str_author2, LEN_AUTHOR2)) { + line = 4; + word = buf + LEN_AUTHOR2; + } + + while(pos < line) { + if(!pos && ((ptr = strstr(word, str_post1)) || + (ptr = strstr(word, str_post2)))) { + ptr[-1] = '\0'; + prints("\033[47;34m %s \033[44;37m%-53.53s" + "\033[47;34m %.4s \033[44;37m%-13s\033[m\n", + head[0], word, ptr, ptr + 5); + } else if (pos < 4) + prints("\033[47;34m %s \033[44;37m%-72.72s" + "\033[m\n", head[pos], word); + + viewed += numbytes; + numbytes = more_readln(fd, buf); + + /* �Ĥ@��Ӫ��F */ + if(!pos && viewed > 79) { + /* �ĤG�椣�O [��....] */ + if(memcmp( buf, head[1], 2)) { + /* Ū�U�@��i�ӳB�z */ + viewed += numbytes; + numbytes = more_readln(fd, buf); + } + } + pos++; + } + if(pos) { + header = 1; + + prints("\033[36m%s\033[m\n", msg_seperator); + line = pos = 4; + } + } + lino = pos; + word = NULL; + } + + /* ���B�z�ޥΪ� & �ި� */ + if((buf[1] == ' ') && (buf[0] == ':' || buf[0] == '>')) + word = "\033[36m"; + else if(!strncmp(buf, "��", 2) || !strncmp(buf, "==>", 3)) + word = "\033[32m"; + + ch1 = buf; + while(1) { + int i; + char e,*ch2; + + if((ch2 = strstr(ch1, "http://"))) + ; + else if((ch2 = strstr(ch1,"gopher://"))) + ; + else if((ch2 = strstr(ch1,"mailto:"))) + ; + else + break; + for(e = 0; ch2[(int)e] != ' ' && ch2[(int)e] != '\n' && + ch2[(int)e] != '\0' && ch2[(int)e] != '"' && + ch2[(int)e] != ';' && ch2[(int)e] != ']'; e++); + for(i = 0; http[i] && i < 80; i++) + if(!strncmp(http[i], ch2, e) && http[(int)e] == 0) + break; + if(!http[i]) { + http[i] = (char *)malloc(e + 1); + strncpy(http[i], ch2, e); + http[i][(int)e] = 0; + pagecount++; + } + ch1 = &ch2[7]; + } + if(word) + outs(word); + { + char msg[500], *pos; + + if(*search_str && (pos = fptr(buf, search_str))) { + char SearchStr[81]; + char buf1[100], *pos1; + + strncpy(SearchStr, pos, strlen(search_str)); + SearchStr[strlen(search_str)] = 0; + searching = 0; + sprintf(msg, "%.*s\033[7m%s\033[m", pos - buf, buf, + SearchStr); + while((pos = fptr(pos1 = pos + strlen(search_str), + search_str))) { + sprintf(buf1, "%.*s\033[7m%s\033[m", pos - pos1, + pos1, SearchStr); + strcat(msg, buf1); + } + strcat(msg, pos1); + outs(Ptt_prints(msg,NO_RELOAD)); + } else + outs(Ptt_prints(buf,NO_RELOAD)); + } + if(word) { + outs("\033[m"); + word = NULL; + } + outch('\n'); + + if(beep) { + bell(); + beep = 0; + } + + if(line < b_lines) /* �@����Ū�� */ + line++; + + if(line == b_lines && searching == -1) { + if(pageno > 0) + more_goto(fd, viewed = pagebreak[--pageno]); + else + searching = 0; + lino = pos = line = 0; + clear(); + continue; + } + + if(scrollup) { + move(line = b_lines, 0); + clrtoeol(); + for(pos = 1; pos < b_lines; pos++) + viewed += more_readln(fd, buf); + } else if(pos == b_lines) /* ���ʿù� */ + scroll(); + else + pos++; + + if(!scrollup && ++lino >= b_lines && pageno < MAX_PAGES - 1) { + pagebreak[++pageno] = viewed; + lino = 1; + } + + if(scrollup) { + lino = scrollup; + scrollup = 0; + } + viewed += numbytes; /* �֭pŪ�L��� */ + } else + line = b_lines; /* end of END */ + + if(promptend && + ((!searching && line == b_lines) || viewed == fsize)) { + /* Kaede ��n 100% �ɤ��� */ + move(b_lines, 0); + if(viewed == fsize) { + if(searching == 1) + searching = 0; + color = 0; + } else if(pageno == 1 && lino == 1) { + if(searching == -1) + searching = 0; + color = 1; + } else + color = 2; + + prints("\033[m\033[%sm �s�� P.%d(%d%%) %s %-30.30s%s", + printcolor[(int)color], + pageno, + (int)((viewed * 100) / fsize), + pagemode ? "\033[30;47m" : "\033[31;47m", + pagemode ? http[pagemode-1] : "(h)\033[30m�D�U \033[31m����[PgUp][", + pagemode ? "\033[31m[TAB]\033[30m���� \033[31m[Enter]\033[30m��w \033[31m��\033[30m���\033[m" : "PgDn][Home][End]\033[30m��в��� \033[31m��[q]\033[30m���� \033[m"); + + + while(line == b_lines || (line > 0 && viewed == fsize)) { + switch((ch = egetch())) { + case ':': + { + char buf[10]; + int i = 0; + + getdata(b_lines - 1, 0, "Goto Page: ", buf, 5, DOECHO); + sscanf(buf, "%d", &i); + if(0 < i && i < MAX_PAGES && (i == 1 || pagebreak[i - 1])) + pageno = i - 1; + else if(pageno) + pageno--; + lino = line = 0; + break; + } + case '/': + { + char ans[4] = "n"; + + *search_str = search_char0; + getdata_buf(b_lines - 1, 0,"[�j�M]����r:", search_str, + 40, DOECHO); + if(*search_str) { + searching = 1; + if(getdata(b_lines - 1, 0, "�Ϥ��j�p�g(Y/N/Q)? [N] ", + ans, 4, LCECHO) && *ans == 'y') + fptr = strstr; + else + fptr = strcasestr; + } + if(*ans == 'q') + searching = 0; + if(pageno) + pageno--; + lino = line = 0; + break; + } + case 'n': + if(*search_str) { + searching = 1; + if(pageno) + pageno--; + lino = line = 0; + } + break; + case 'N': + if(*search_str) { + searching = -1; + if(pageno) + pageno--; + lino = line = 0; + } + break; + case 'r': + case 'R': + case 'Y': + close(fd); + return 7; + case 'y': + close(fd); + return 8; + case 'A': + close(fd); + return 9; + case 'a': + close(fd); + return 10; + case 'F': + close(fd); + return 11; + case 'B': + close(fd); + return 12; + case KEY_LEFT: + if(pagemode) { + pagemode = 0; + *search_str = 0; + if(pageno) + pageno--; + lino = line = 0; + break; + } + close(fd); + return 6; + case 'q': + close(fd); + return 0; + case 'b': + close(fd); + return 1; + case 'f': + close(fd); + return 3; + case ']': /* Kaede ���F�D�D�\Ū��K */ + close(fd); + return 4; + case '[': /* Kaede ���F�D�D�\Ū��K */ + close(fd); + return 2; + case '=': /* Kaede ���F�D�D�\Ū��K */ + close(fd); + return 5; + case Ctrl('F'): + case KEY_PGDN: + line = 1; + break; + case 't': + if(viewed == fsize) { + close(fd); + return 4; + } + line = 1; + break; + case ' ': + if(viewed == fsize) { + close(fd); + return 3; + } + line = 1; + break; + case KEY_RIGHT: + if(viewed == fsize) { + close(fd); + return 0; + } + line = 1; + break; + case '\r': + case '\n': + if(pagemode) { + more_web(http[pagemode-1],YEA); + pagemode = 0; + *search_str = 0; + if(pageno) + pageno--; + lino = line = 0; + break; + } + case KEY_DOWN: + if(viewed == fsize || + (promptend == 2 && (ch == '\r' || ch == '\n'))) { + close(fd); + return 3; + } + line = t_lines - 2; + break; + case '$': + case 'G': + case KEY_END: + line = t_lines; + break; + case '0': + case 'g': + case KEY_HOME: + pageno = line = 0; + break; + case 'h': + case 'H': + case '?': + /* Kaede Buggy ... */ + show_help(more_help); + if(pageno) + pageno--; + lino = line = 0; + break; + case 'E': + if(HAS_PERM(PERM_SYSOP) && strcmp(fpath, "etc/ve.hlp")) { + close(fd); + vedit(fpath, NA, NULL); + return 0; + } + break; + case Ctrl('C'): + cal(); + if(pageno) + pageno--; + lino = line = 0; + break; + + case Ctrl('T'): + getdata(b_lines - 2, 0, "��o�g�峹���J��Ȧs�ɡH[y/N] ", + buf, 4, LCECHO); + if(buf[0] == 'y') { + char tmpbuf[128]; + + setuserfile(tmpbuf, ask_tmpbuf(b_lines - 1)); + sprintf(buf, "cp -f %s %s", fpath, tmpbuf); + system(buf); + } + if(pageno) + pageno--; + lino = line = 0; + break; +#if 0 + case Ctrl('I'): + if(!pagecount) + break; + pagemode = (pagemode % pagecount) + 1; + strncpy(search_str,http[pagemode-1],80); + search_str[80] =0; + fptr = strstr; + if(pageno) + pageno--; + lino = line = 0; + break; +#endif + case KEY_UP: + line = -1; + break; + case Ctrl('B'): + case KEY_PGUP: + if(pageno > 1) { + if(lino < 2) + pageno -= 2; + else + pageno--; + lino = line = 0; + } else if(pageno && lino > 1) + pageno = line = 0; + break; + case Ctrl('H'): + if(pageno > 1) { + if(lino < 2) + pageno -= 2; + else + pageno--; + lino = line = 0; + } else if(pageno && lino > 1) + pageno = line = 0; + else { + close(fd); + return 1; + } + } + } + + if(line > 0) { + move(b_lines, 0); + clrtoeol(); + refresh(); + } else if(line < 0) { /* Line scroll up */ + if(pageno <= 1) { + if(lino == 1 || !pageno) { + close(fd); + return 1; + } + if(header && lino <= 5) { + more_goto(fd, viewed = pagebreak[scrollup = lino = + pageno = 0] = 0); + clear(); + } + } + if(pageno && lino > 1 + local) { + line = (lino - 2) - local; + if(pageno > 1 && viewed == fsize) + line += local; + scrollup = lino - 1; + more_goto(fd, viewed = pagebreak[pageno - 1]); + while(line--) + viewed += more_readln(fd, buf); + } else if(pageno > 1) { + scrollup = b_lines - 1; + line = (b_lines - 2) - local; + more_goto(fd, viewed = pagebreak[--pageno - 1]); + while(line--) + viewed += more_readln(fd, buf); + } + line = pos = 0; + } else { + pos = 0; + more_goto (fd, viewed = pagebreak[pageno]); + move(0,0); + clear(); + } + } + } + + close(fd); + if(promptend) { + pressanykey(); + clear(); + } else + outs(reset_color); + return 0; +} + +static int more_web(char *fpath, int promptend) { + char *ch, *ch1 = NULL; + char *hostname = fpath,userfile[MAXPATHLEN],file[MAXPATHLEN]="/"; + char genbuf[200]; + time_t dtime; +#if !defined(USE_LYNX) && defined(USE_PROXY) + int a; + FILE *fp; + struct hostent *h; + struct sockaddr_in sin; +#endif + + if((ch = strstr(fpath, "mailto:"))) { + if(!HAS_PERM(PERM_LOGINOK)) { + move(b_lines - 1,0); + outs("\033[41m �z���v�������L�k�ϥ�internet mail... \033[m"); + refresh(); + return 0; + } + if(!invalidaddr(&ch[7]) && + getdata(b_lines - 1, 0, "[�H�H]�D�D�G", genbuf, 40, DOECHO)) + do_send(&ch[7], genbuf); + else { + move(b_lines - 1,0); + outs("\033[41m ���H�Hemail �� ���D ���~... \033[m"); + refresh(); + } + return 0; + } + if((ch = strstr(fpath, "gopher://"))) { + item_t item; + + strcpy(item.X.G.server, &ch[9]); + strcpy(item.X.G.path, "1/"); + item.X.G.port = 70; + gem(fpath , &item, 0); + return 0; + } + if((ch = strstr(fpath, "http://"))) + hostname=&ch[7]; + if((ch = strchr(hostname, '/'))) { + *ch = 0; + if(&ch1[1]) + strcat(file,&ch[1]); + } + if(file[strlen(file) - 1] == '/') + strcat(file,"index.html"); + move(b_lines-1,0); + clrtoeol(); +#ifdef USE_PROXY + sprintf(genbuf, "\033[33;44m ���b�s��%s.(proxy:%s).....�еy��....\033[m", + hostname, PROXYSERVER); +#else + sprintf(genbuf, "\033[33;44m ���b�s��%s......�еy��....\033[m", hostname); +#endif + outs(genbuf); + refresh(); + +#ifdef LOCAL_PROXY +/* ���� local disk �� proxy */ + time(&dtime); + sprintf(userfile,"hproxy/%s%s",hostname,file); + if(dashf(userfile) && (dtime - dasht(userfile)) < HPROXYDAY * 24 * 60 + && more(userfile,promptend)) { + return 1; + } + ch=userfile - 1; + while((ch1 = strchr(ch + 1,'/'))) { + *ch1 = 0; + if(!dashd(ch)) + mkdir(ch+1,0755); + chdir(ch+1); + *ch1 = '/'; + ch = ch1; + } + chdir(BBSHOME); +#endif + +#ifndef USE_LYNX +#ifdef USE_PROXY + if(!(h = gethostbyname(PROXYSERVER))) { + outs("\033[33;44m �䤣��o��proxy server!..\033[m"); + refresh(); + return; + } + ()memset((char *)&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + + if(h == NULL) + sin.sin_addr.s_addr = inet_addr(PROXYSERVER); + else + ()memcpy(&sin.sin_addr.s_addr, h->h_addr, h->h_length); + + sin.sin_port = htons((ushort)PROXYPORT); /* HTTP port */ + a = socket(AF_INET, SOCK_STREAM, 0); + if((connect(a, (struct sockaddr *) & sin, sizeof sin)) < 0) { + outs("\033[1;44m �s����proxy����ڵ� ! \033[m"); + refresh(); + return; + } + sprintf(genbuf,"GET http://%s/%s HTTP/1.1\n",hostname,file); +#else + if(!(h = gethostbyname(hostname))) { + outs("\033[33;44m �䤣��o��server!..\033[m"); + refresh(); + return; + } + ()memset((char *) &sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + + if(h == NULL) + sin.sin_addr.s_addr = inet_addr(hostname); + else + ()memcpy(&sin.sin_addr.s_addr, h->h_addr, h->h_length); + + sin.sin_port = htons((ushort)80); + a = socket(AF_INET, SOCK_STREAM, 0); + if((connect(a, (struct sockaddr *) & sin, sizeof sin)) < 0) { + outs("\033[1;44m �s������ڵ� ! \033[m"); + refresh(); + return; + } + sprintf(genbuf, "GET %s\n", file); +#endif + + for(i = strlen(file); file[i - 1] != '/' && i > 0 ; i--); + file[i] = 0; + + i = strlen(genbuf); + write(a, genbuf, i); + +#define BLANK 001 +#define ISPRINT 002 +#define PRE 004 +#define CENTER 010 + if((fp = fopen(userfile,"w"))) { + int flag = 2, c; + char path[MAXPATHLEN]; + unsigned char j, k; + + while((i = read(a,genbuf,200))) { + if(i < 0) + return; + genbuf[i]=0; + + for(j = 0, k = 0; genbuf[j] && j < i; j++) { + if((flag & ISPRINT) && genbuf[j] == '<') + flag |= BLANK; + else if((flag & ISPRINT) && genbuf[j] == '>') + flag &= ~BLANK; + else { + if(!(flag & BLANK)) { + if(j != k && (genbuf[j] != '\n' || flag & PRE)) + genbuf[k++] = genbuf[j]; + } else { + switch(char_lower(genbuf[j])) { + case 'a': + break; + case 'b': + if(genbuf[j + 1] == 'r' && genbuf[j + 2] == '>') + genbuf[k++] = '\n'; + break; + case 'h': + if(genbuf[j + 1] == 'r' && + (genbuf[j + 2] == '>' || + genbuf[j + 2] == 's')) { + strncpy(&genbuf[k], "\n--\n", 4); + k += 4; + } + break; + case 'l': + if(genbuf[j + 1] == 'i' && genbuf[j + 2]=='>') { + strncpy(&genbuf[k], "\n�� ", 4); + k += 4; + } + break; + case 'p': + if(genbuf[j + 1]=='>') { + genbuf[k++] = '\n'; + genbuf[k++] = '\n'; + } else if(genbuf[j + 1] == 'r' && + genbuf[j + 2] == 'e') + flag ^= PRE; + break; + case 't': + if(genbuf[j + 1] == 'd' && genbuf[j + 2]=='>') { + strncpy(&genbuf[k], "\n-\n", 3); + k += 3; + } + break; + } + } + if((genbuf[j] & 0x80) && (flag & ISPRINT)) + flag &= ~ISPRINT; + else + flag |= ISPRINT; + } + } + genbuf[k]=0; + fputs(genbuf, fp); + } + fclose(fp); + close(a); + return more(userfile, promptend); + } + return 0; +#else /* use lynx dump */ + sprintf(genbuf, "lynx -dump http://%s%s > %s", hostname, file, userfile); + system(genbuf); + return more(userfile, promptend); +#endif +} diff --git a/mbbsd/name.c b/mbbsd/name.c new file mode 100644 index 00000000..2f84a1fe --- /dev/null +++ b/mbbsd/name.c @@ -0,0 +1,473 @@ +/* $Id: name.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <signal.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +extern char *str_space; +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ + +word_t *toplev = NULL; +static word_t *current = NULL; +static char *msg_more = "\033[7m-- More --\033[m"; + +typedef char (*arrptr)[]; +/* name complete for user ID */ + +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; + } + 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) + strcpy(cwbuf[num++], cwlist[n]); + } + return num; +} + +static void FreeNameList() { + word_t *p, *temp; + + for(p = toplev; p; p = temp) { + temp = p->next; + free(p->word); + free(p); + } +} + +void CreateNameList() { + if(toplev) + FreeNameList(); + toplev = current = NULL; +} + +void AddNameList(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(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; +} + +int InNameList(char *name) { + word_t *p; + + for(p = toplev; p; p = p->next) + if(!strcmp(p->word, name)) + return 1; + return 0; +} + +void ShowNameList(int row, int column, 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, char *listfile, char *msg) { + FILE *fp; + char genbuf[200]; + + if((fp = fopen(listfile, "r"))) { + while(fgets(genbuf, STRLEN, fp)) { + strtok(genbuf, str_space); + if(!InNameList(genbuf)) { + AddNameList(genbuf); + (*reciper)++; + } else { + RemoveNameList(genbuf); + (*reciper)--; + } + } + fclose(fp); + ShowNameList(3, 0, msg); + } +} + +static int NumInList(word_t *list) { + register int i; + + for(i = 0; list; i++) + list = list->next; + return i; +} + +int chkstr(char *otag, char *tag, char *name) { + char ch, *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(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; +} + +void namecomplete(char *prompt, char *data) { + char *temp; + word_t *cwlist, *morelist; + int x, y, origx, origy; + 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); + getyx(&origy, &origx); + standout(); + prints("%*s", IDLEN + 1, ""); + standend(); + move(y, x); + refresh(); + + while((ch = igetch()) != EOF) { + if(ch == '\n' || ch == '\r') { + *temp = '\0'; + outc('\n'); + if(NumInList(cwlist) == 1) + strcpy(data, cwlist->word); + ClearSubList(cwlist); + break; + } + if(ch == ' ') { + int col, len; + + if(NumInList(cwlist) == 1) { + strcpy(data, cwlist->word); + move(y, x); + outs(data + count); + count = strlen(data); + temp = data + count; + getyx(&y, &x); + continue; + } + clearbot = YEA; + col = 0; + if(!morelist) + morelist = cwlist; + len = MaxLen(morelist, p_lines); + move(2, 0); + clrtobot(); + printdash("������T�@����"); + while(len + col < 80) { + 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) { + move(b_lines, 0); + outs(msg_more); + } + move(y, x); + continue; + } + if(ch == '\177' || ch == '\010') { + if(temp == data) + continue; + temp--; + count--; + *temp = '\0'; + ClearSubList(cwlist); + cwlist = GetSubList(data, toplev); + morelist = NULL; + x--; + move(y, x); + outc(' '); + move(y, x); + 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; + move(y, x); + outc(ch); + x++; + } + } + if(ch == EOF) + /* longjmp(byebye, -1); */ + raise(SIGHUP); /* jochang: don't know if this is necessary... */ + outc('\n'); + refresh(); + if(clearbot) { + move(2, 0); + clrtobot(); + } + if(*data) { + move(origy, origx); + outs(data); + outc('\n'); + } +} + +void usercomplete(char *prompt, char *data) { + char *temp; + char *cwbuf, *cwlist; + int cwnum, x, y, origx, origy; + int clearbot = NA, count = 0, morenum = 0; + char ch; + + cwbuf = malloc(MAX_USERS * (IDLEN + 1)); + cwlist = u_namearray((arrptr)cwbuf, &cwnum, ""); + temp = data; + + outs(prompt); + clrtoeol(); + getyx(&y, &x); + getyx(&origy, &origx); + standout(); + prints("%*s", IDLEN + 1, ""); + standend(); + move(y, x); + while((ch = igetch()) != EOF) { + if(ch == '\n' || ch == '\r') { + int i; + char *ptr; + + *temp = '\0'; + outc('\n'); + ptr = (char *)cwlist; + for(i = 0; i < cwnum; i++) { + if(strncasecmp(data, ptr, IDLEN + 1) == 0) + strcpy(data, ptr); + ptr += IDLEN + 1; + } + break; + } else if(ch == ' ') { + int col, len; + + if(cwnum == 1) { + strcpy(data, (char *)cwlist); + move(y, x); + outs(data + count); + count = strlen(data); + temp = data + count; + getyx(&y, &x); + continue; + } + clearbot = YEA; + col = 0; + len = UserMaxLen((arrptr)cwlist, cwnum, morenum, p_lines); + move(2, 0); + clrtobot(); + printdash("�ϥΪ̥N���@����"); + while(len + col < 79) { + int i; + + for(i = 0; morenum < cwnum && i < p_lines; i++) { + move(3 + i, col); + prints("%s ", 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); + outs(msg_more); + } else + morenum = 0; + move(y, x); + continue; + } else if(ch == '\177' || ch == '\010') { + if(temp == data) + continue; + temp--; + count--; + *temp = '\0'; + cwlist = u_namearray((arrptr)cwbuf, &cwnum, data); + morenum = 0; + x--; + move(y, x); + outc(' '); + move(y, x); + continue; + } else if(count < STRLEN && isprint(ch)) { + int n; + + *temp++ = ch; + *temp = '\0'; + n = UserSubArray((arrptr)cwbuf, (arrptr)cwlist, cwnum, ch, count); + if(n == 0) { + temp--; + *temp = '\0'; + continue; + } + cwlist = cwbuf; + count++; + cwnum = n; + morenum = 0; + move(y, x); + outc(ch); + x++; + } + } + free(cwbuf); + if(ch == EOF) + /* longjmp(byebye, -1); */ + raise(SIGHUP); /* jochang: don't know if this is necessary */ + outc('\n'); + refresh(); + if(clearbot) { + move(2, 0); + clrtobot(); + } + if(*data) { + move(origy, origx); + outs(data); + outc('\n'); + } +} diff --git a/mbbsd/osdep.c b/mbbsd/osdep.c new file mode 100644 index 00000000..967a4db0 --- /dev/null +++ b/mbbsd/osdep.c @@ -0,0 +1,79 @@ +/* $Id: osdep.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> + +#if defined(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(long *total, long *used) { + double percent = -1; + char buf[101]; + FILE *fp; + + if((fp = fopen("/proc/meminfo","r"))) { + while(fgets(buf, 100, fp) && buf[0] != 'S'); + if(sscanf(buf + 6, "%ld %ld", total, used) == 2) + if(*total != 0) + percent = (double)*used / (double)*total; + fclose(fp); + } + return percent; +} + +#elif __FreeBSD__ >=4 + +#include <kvm.h> + +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]; +} + +double swapused(long *total, long *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 diff --git a/mbbsd/othello.c b/mbbsd/othello.c new file mode 100644 index 00000000..47b8cef3 --- /dev/null +++ b/mbbsd/othello.c @@ -0,0 +1,541 @@ +/* $Id: othello.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern char *BBSName; + +#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) + +static char nowx = 3, nowy = 3; +static char *CHESS_TYPE[] = {NONE_CHESS, HINT_CHESS, BLACK_CHESS, WHITE_CHESS}; +static char DIRX[] = {-1,-1,-1, 0, 1, 1, 1, 0}; +static char DIRY[] = {-1, 0, 1, 1, 1, 0,-1,-1}; +static char number[2]; + +static char pass = 0; +static char if_hint = 0; +static int think, which_table; + +static char nowboard[10][10]= +{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}; +static 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 char table[NR_TABLE + 1][10][10]; +static void print_chess(int x, int y, char chess) { + move(STARTX - 1 + x * 2, STARTY - 2 + y * 4); + if(chess != HINT || if_hint == 1) + prints(CHESS_TYPE[(int)chess]); + else + prints(CHESS_TYPE[NONE]); + refresh(); +} + +extern userec_t cuser; + +static void printboard() { + int i; + + move(STARTX, STARTY); + prints("�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); + prints ("�x �x �x �x �x �x �x �x �x"); + move(STARTX + 2 + i * 2, STARTY); + prints ("�u�w�q�w�q�w�q�w�q�w�q�w�q�w�q�w�t"); + } + move(STARTX + 1 + i * 2, STARTY); + prints("�x �x �x �x �x �x �x �x �x"); + move(STARTX + 2 + i * 2, STARTY); + prints("�|�w�r�w�r�w�r�w�r�w�r�w�r�w�r�w�}"); + print_chess(4, 4, WHITE); + print_chess(5, 5, WHITE); + print_chess(4, 5, BLACK); + print_chess(5, 4, BLACK); + move(3, 56); + prints("(��)%s",cuser.userid); + move(3, 72); + prints(": 02"); + move(4, 56); + prints("(��)�q�� : 02"); + move(6, 56); + prints("�� �i�H�U���B"); + move(7, 56); + prints("[q] �h�X"); + move(8, 56); + prints("[h] �}��/���� ����"); + move(9,56); + prints("[Enter][Space] �U��"); + move(10, 56); + prints("�W:��, i"); + move(11, 56); + prints("�U:��, k"); + move(12, 56); + prints("��:��, j"); + move(13, 56); + prints("�k:��, l"); +} + +static int get_key(char nowx, char nowy) { + int ch; + + move(STARTX - 1 + nowx * 2, STARTY - 1 + nowy * 4); + ch = igetkey(); + move(STARTX - 1 + nowx * 2, STARTY - 2 + nowy * 4); + if(nowboard[(int)nowx][(int)nowy] != HINT || if_hint==1) + outs(CHESS_TYPE[(int)nowboard[(int)nowx][(int)nowy]]); + 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(char color) { + int i, j, temp = 0; + + for(i = 1; i <= 8; i++) + for(j = 1; j <= 8; j++) { + if(nowboard[i][j] == HINT) + nowboard[i][j] = NONE; + if(if_can_put(i, j, color, nowboard)) { + nowboard[i][j] = HINT; + temp++; + } + print_chess(i, j, 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(int quit) { + FILE *fp,*fp1; + char *opponent[] = {"","CD-65","","����","�p��","","�j�H","�M�a"}; + + move(STARTX - 1, 30); + prints (" "); + move(22, 35); + fp = fopen(LOGFILE, "a"); + if(!quit) { + fp1 = fopen(SECRET, "a"); + if(fp1) { + fprintf(fp1, "%d,%d,%s,%02d,%02d\n", think, which_table, + cuser.userid, number[0], number[1]); + fclose(fp1); + } + } + + if(quit) { + if(number[0] == 2 && number[1] == 2) { + if(fp) + fclose(fp); + return; + } + fprintf(fp, "�b%s�Ť�, %s�{�}��k\n", opponent[think], cuser.userid); + if(fp) + fclose(fp); + return; + } + if(number[0] > number[1]) { + prints("�AĹ�F�q��%02d�l", number[0] - number[1]); + if(think == 6 && number[0] - number[1] >= 50) + demoney(200); + if(think == 7 && number[0] - number[1] >= 40) + demoney(200); + if(fp) + fprintf(fp, "�b%s�Ť�, %s�H %02d:%02d Ĺ�F�q��%02d�l\n", + opponent[think], cuser.userid, number[0], number[1], + number[0] - number[1]); + } else if(number[1] > number[0]) { + prints("�q��Ĺ�F�A%02d�l", number[1] - number[0]); + if(fp) { + fprintf(fp, "�b%s�Ť�, ", opponent[think]); + if(number[1] - number[0] > 20) + fprintf(fp, "�q���H %02d:%02d �G�q%s %02d�l\n", number[1], + number[0], cuser.userid, number[1] - number[0]); + else + fprintf(fp, "�q���H %02d:%02d Ĺ�F%s %02d�l\n", number[1], + number[0], cuser.userid, number[1] - number[0]); + } + } else { + prints("�A�M�q����������!!"); + if(fp) + fprintf(fp, "�b%s�Ť�, %s�M�q���H %02d:%02d �����F����\n", + opponent[think], cuser.userid, number[1], number[0]); + } + if(fp) + fclose(fp); + move(1,1); + igetkey(); +} + +static void othello_redraw() { + int i, j; + + for(i = 1; i <= 8; i++) + for(j = 1; j <= 8; j++) + print_chess(i, j, nowboard[i][j]); +} + +static int player(char color) { + int ch; + + if(get_hint(color)) { + while(true) { + ch = get_key(nowx,nowy); + switch(ch) { + case 'J': + case 'j': + case KEY_LEFT: + nowy--; + break; + case 'L': + case 'l': + case KEY_RIGHT: + nowy++; + break; + case 'I': + case 'i': + case KEY_UP: + nowx--; + break; + case 'K': + case 'k': + case KEY_DOWN: + nowx++; + break; + case ' ': + case '\r': + if(nowboard[(int)nowx][(int)nowy] != HINT) + break; + pass = 0; + nowboard[(int)nowx][(int)nowy] = color; + eat(nowx, nowy, color, nowboard); + print_chess(nowx, nowy, color); + return true; + case 'q': + end_of_game(1); + return false; + case 'H': + case 'h': + if_hint = if_hint^1; + othello_redraw(); + break; + } + if(nowx == 9) + nowx=1; + if(nowx == 0) + nowx=8; + if(nowy == 9) + nowy=1; + if(nowy == 0) + nowy=8; + } + } else { + pass++; + if(pass == 1) { + move(23, 34); + prints("�A���ݩ��o�@�B!!"); + igetch(); + move(28,23); + prints(" "); + } else { + end_of_game(0); + return false; + } + } + return 0; +} + +static void init() { + int i, j, i1, j1; + + nowx = 4; + nowy = 4; + number[0] = 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); + table[0][i][j] = init_table[0][i1][j1]; + table[1][i][j] = init_table[1][i1][j1]; + } + for(i = 1; i <= 8; i++) + for(j = 1; j <= 8; j++) + nowboard[i][j] = NONE; + nowboard[4][4] = nowboard[5][5] = WHITE; + nowboard[4][5] = nowboard[5][4] = BLACK; +} + +static void report() { + int i, j; + + number[0] = number[1] = 0; + for(i = 1; i <= 8; i++) + for(j = 1; j <= 8; j++) + if(nowboard[i][j] == BLACK) + number[0]++; + else if(nowboard[i][j] == WHITE) + number[1]++; + move(3, 60); + prints("%s", cuser.userid); + move(3, 72); + prints(": %02d", number[0]); + move(4, 60); + prints("�q�� : %02d", number[1]); +} + +static int EVL(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 += table[table_number][a][b]; + else + points -= table[table_number][a][b]; + } + return ((color == BLACK) ? points : -points); +} + +static int alphabeta(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(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(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(chessboard, color, table); + return ((level & 1) ? alpha : beta); +} + +static int Computer(int thinkstep, int table) { + int i, j, maxi = 0, maxj = 0, level = 1; + char chessboard[10][10]; + int alpha = -10000, k; + if((number[0] + 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,nowboard)) { + memcpy(chessboard, nowboard, sizeof(char) * 100); + eat(i, j, WHITE, chessboard); + k = alphabeta(alpha, 10000, level + 1, chessboard, thinkstep, + BLACK, table); + if(k > alpha) { + alpha = k; + maxi = i; + maxj = j; + } + } + } + if(alpha != -10000) { + eat(maxi, maxj, WHITE, nowboard); + pass = 0; + nowx = maxi; + nowy = maxj; + } else { + move(23, 30); + prints("�q�����o�@�B��!!"); + pass++; + if(pass == 2) { + move(23, 24); + prints(" "); + end_of_game(0); + return false; + } + igetch(); + move(23, 24); + prints(" "); + } + return true; +} + +static int choose() { + char thinkstep[2]; + + move(2, 0); + prints("�п������:"); + move(5, 0); + prints("(1) CD-65\n"); /* �Q 1 �B */ + prints("(2) ����\n"); /* �Q 3 �B */ + prints("(3) �p��\n"); /* �Q 4 �B */ + do { + getdata(4, 0, "�п�ܤ@�ӹ�H�M�z�若:(1~5)", thinkstep, 2, LCECHO); + } 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() { + lockreturn0(OTHELLO, LOCK_MULTI); + clear(); + init(); + think = choose(); + showtitle("�¥մ�", BBSName); + printboard(); + which_table = rand() % NR_TABLE; + while(true) { + move(STARTX - 1, 30); + prints("����A�U�F..."); + if(!player(BLACK)) + break; + report(); + othello_redraw(); + if(number[0] + number[1] == 64) { + end_of_game(0); + break; + } + move(STARTX - 1, 30); + prints("�q����Ҥ�..."); + refresh(); + if(!Computer(think, which_table)) + break; + report(); + othello_redraw(); + if(number[0] + number[1] == 64) { + end_of_game(0); + break; + } + } + more(LOGFILE, YEA); + unlockutmpmode(); + return 1; +} diff --git a/mbbsd/page.c b/mbbsd/page.c new file mode 100644 index 00000000..c77ef421 --- /dev/null +++ b/mbbsd/page.c @@ -0,0 +1,130 @@ +/* $Id: page.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "proto.h" + +#define hpressanykey(a) {move(22, 0); prints(a); pressanykey();} +static void filt_railway(char* fpath) { + char buf[256], tmppath[32]; + FILE* fp = fopen(fpath, "w"), *tp; + + sprintf(tmppath, "%s.railway", fpath); + if(!fp || !(tp = fopen(tmppath, "r"))) + return; + + while(fgets(buf, 255, tp)) { + if(strstr(buf, "INLINE")) + continue; + if(strstr(buf, "LINK")) + break; + fprintf(fp, "%s", buf); + } + fclose(fp); + fclose(tp); + unlink(tmppath); +} + +extern userec_t cuser; + +int main_railway() { + fileheader_t mhdr; + char genbuf[200]; + int from, to, time_go, time_reach; + char tt[2], type[2]; + char command[256], buf[8]; + char *addr[]= { + "��", "�K��", "�C��", "����", "����", "�n��", "�Q�s", "�x�_", "�U��", + "�O��", "��L", "�s��", "�a�q", "���", "���c", "���c", "�H��", "����", + "��f", "�s��", "�˥_", "�s��", "���s", "�T��", "�˫n", "�y��", "�״I", + "�ͤ�", "�j�s", "���s", "�s��", "�ըF��", "�s�H", "�q�]", "�b��", + "��n", "�j��", "�O����", "�M��", "�F��", "�s��", "�j�{", "�l��", + "�]��", "�n��", "���r", "�T�q", "�ӿ�", "���w", "�Z��", "��", "��l", + "�x��", "�Q��", "���\\", "����", "���", "���L", "�ùt", "���Y", + "�Ф�", "�G��", "�L��", "�ۺh", "�椻", "��n", "���t", "�j�L", + "����", "�Ÿq", "���W", "�n�t", "���", "�s��", "�h��", "�L����", + "����", "�ުL", "����", "�s��", "�ñd", "�x�n", "�O�w", "���w", + "�j��", "����", "���s", "���Y", "����", "����", "����", "��s", + "�E����", "�̪F", NULL, NULL + }; + + setutmpmode(RAIL_WAY); + clear(); + move(0,25); + prints("\033[1;37;45m �����d�ߨt�� \033[1;44;33m�@��:Heat\033[m"); + move(1,0); + outs("\033[1;33m + 1.�� 16.���c 31.�s�� 46.���r 61.�Ф� 76.�L���� 91.���� + 2.�K�� 17.�H�� 32.�ըF�� 47.�T�q 62.�G�� 77.���� 92.��s + 3.�C�� 18.���� 33.�s�H 48.�ӿ� 63.�L�� 78.�ުL 93.�E���� + 4.���� 19.��f 34.�q�] 49.���w 64.�ۺh 79.���� 94.�̪F + 5.���� 20.�s�� 35.�b�� 50.�Z�� 65.�椻 80.�s�� + 6.�n�� 21.�˥_ 36.��n 51.�� 66.��n 81.�ñd + 7.�Q�s 22.�s�� 37.�j�� 52.��l 67.���t 82.�x�n + 8.�x�_ 23.���s 38.�O���� 53.�x�� 68.�j�L 83.�O�w + 9.�U�� 24.�T�� 39.�M�� 54.�Q�� 69.���� 84.���w +10.�O�� 25.�˫n 40.�F�� 55.���\\ 70.�Ÿq 85.�j�� +11.��L 26.�y�� 41.�s�� 56.���� 71.���W 86.���� +12.�s�� 27.�״I 42.�j�{ 57.��� 72.�n�t 87.���s +13.�a�q 28.�ͤ� 43.�l�� 58.���L 73.��� 88.���Y +14.��� 29.�j�s 44.�]�� 59.�ùt 74.�s�� 89.���� +15.���c 30.���s 45.�n�� 60.���Y 75.�h�� 90.����\033[m"); + + getdata(17, 0, "\033[1;35m�A�T�w�n�j�M��?[y/n]:\033[m", buf, 2, LCECHO); + if(buf[0] != 'y' && buf[0] != 'Y') + return 0; + while(1) + if(getdata(18, 0, "\033[1;35m�п�J�_��(1-94):\033[m", buf, 3, LCECHO) && + (from = atoi(buf)) >= 1 && from <= 94) + break; + while(1) + if(getdata(18, 40, "\033[1;35m�п�J�ت��a(1-94):\033[m", + buf, 3, LCECHO) && + (to = atoi(buf)) >= 1 && to <= 94) + break; + while(1) + if(getdata(19, 0, "\033[1;35m�п�J�ɶ��Ϭq(0-23) ��:\033[m", + buf,3,LCECHO) && + (time_go = atoi(buf)) >= 0 && time_go <= 23) + break; + while(1) + if(getdata(19, 40, "\033[1;35m��:\033[m", buf, 3, LCECHO) && + (time_reach=atoi(buf)) >= 0 && time_reach <= 23) + break; + while(1) + if(getdata(20, 0, "\033[1;35m�Q�d�� 1:�︹�֨� 2:���q����\033[m", + type,2,LCECHO) && (type[0] == '1' || type[0] == '2')) + break; + while(1) + if(getdata(21, 0, "\033[1;35m���d�� 1:�X�o�ɶ� 2:��F�ɶ�\033[m", + tt, 2, LCECHO) && + (tt[0]=='1' || tt[0]=='2')) + break; + sethomepath(genbuf, cuser.userid); + stampfile(genbuf, &mhdr); + strcpy(mhdr.owner, "Ptt�j�M��"); + strncpy(mhdr.title, "�����ɨ�j�M���G", TTLEN); + mhdr.savemode = '\0'; + + sprintf(command,"echo \"from-station=%s&to-station=%s" + "&from-time=%02d00&to-time=%02d00&tt=%s&type=%s\" | " + "lynx -dump -post_data " + "\"http://www.railway.gov.tw/cgi-bin/timetk.cgi\" > %s.railway", + addr[from - 1], addr[to - 1], time_go, time_reach, + (tt[0] == '1') ? "start" : "arriv", + (type[0] == '1') ? "fast" : "slow", genbuf); + + system(command); + filt_railway(genbuf); + sethomedir(genbuf, cuser.userid); + if(append_record(genbuf, &mhdr, sizeof(mhdr)) == -1) + return -1; + hpressanykey("\033[1;31m�ڭ̷|��j�M���G�ܧִN�H���A�� ^_^\033[m"); + return 0; +} diff --git a/mbbsd/passwd.c b/mbbsd/passwd.c new file mode 100644 index 00000000..28a31119 --- /dev/null +++ b/mbbsd/passwd.c @@ -0,0 +1,138 @@ +/* $Id: passwd.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "proto.h" + +extern char *fn_passwd; + +static userec_t *passwd_image = NULL; +static int passwd_image_size; +static int semid = -1; + +#ifndef SEM_R +#define SEM_R 0400 +#endif + +#ifndef SEM_A +#define SEM_A 0200 +#endif + +#ifndef __FreeBSD__ +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + u_short *array; /* array for GETALL & SETALL */ + struct seminfo *__buf; /* buffer for IPC_INFO */ +}; +#endif + +int passwd_mmap() { + int fd; + + fd = open(fn_passwd, O_RDWR); + if(fd > 0) + { + struct stat st; + + fstat(fd, &st); + passwd_image_size = st.st_size; + passwd_image = mmap(NULL, passwd_image_size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if(passwd_image == (userec_t *)-1) { + perror("mmap"); + return -1; + } +/* rocker 011018: after success get mmap, close file descript */ + close (fd); + + 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); + } + } + } else { + perror(fn_passwd); + return -1; + } + return 0; +} + +extern int usernum; +int passwd_update_money(int num) { + int money; + if(num < 1 || num > MAX_USERS) + return -1; + money = moneyof(num); + memcpy(&passwd_image[num - 1].money, &money, sizeof(int)); + return 0; +} + +int passwd_update(int num, userec_t *buf) { + if(num < 1 || num > MAX_USERS) + return -1; + buf->money = moneyof(num); + memcpy(&passwd_image[num - 1], buf, sizeof(userec_t)); + return 0; +} + +int passwd_query(int num, userec_t *buf) { + if(num < 1 || num > MAX_USERS) + return -1; + memcpy(buf, &passwd_image[num - 1], sizeof(userec_t)); + return 0; +} + +int passwd_apply(int (*fptr)(userec_t *)) { + int i; + + for(i = 0; i < MAX_USERS; i++) + if((*fptr)(&passwd_image[i]) == QUIT) + return QUIT; + return 0; +} + +void passwd_lock() { + struct sembuf buf = { 0, -1, SEM_UNDO }; + + if(semop(semid, &buf, 1)) { + perror("semop"); + exit(1); + } +} + +void passwd_unlock() { + struct sembuf buf = { 0, 1, SEM_UNDO }; + + if(semop(semid, &buf, 1)) { + perror("semop"); + exit(1); + } +} diff --git a/mbbsd/read.c b/mbbsd/read.c new file mode 100644 index 00000000..b92f95e7 --- /dev/null +++ b/mbbsd/read.c @@ -0,0 +1,998 @@ +/* $Id: read.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +#define MAXPATHLEN 256 + +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char currowner[IDLEN + 2]; +extern char currtitle[44]; +extern char currauthor[IDLEN + 2]; +extern char *str_reply; +extern char *msg_fwd_ok; +extern char *msg_fwd_err1; +extern char *msg_fwd_err2; +extern int currmode; +extern unsigned int currstat; +extern char currboard[]; /* name of currently selected board */ +extern int KEY_ESC_arg; +extern int curredit; +extern char *msg_mailer; +extern int currbid; +extern bcache_t *brdshm; + +char currdirect[64]; +static fileheader_t *headers = NULL; +static int last_line; +static int hit_thread; + +/* rocker.011018: add new tag */ + +extern int rget(); +extern char getans(); +extern void touchdircache(); +extern int get_fileheader_cache(); + +/* rocker.011018: �s��tag�覡 */ + +#define MAXTAGS 256 + +#include <sys/mman.h> + +typedef struct +{ + time_t chrono; + int recno; +} TagItem; + + +/* ----------------------------------------------------- */ +/* Tag List ���� */ +/* ----------------------------------------------------- */ + + +int TagNum; /* tag's number */ +TagItem TagList[MAXTAGS]; /* ascending list */ + +void +UnTagger (int locus) +{ + if (locus > TagNum) return; + + TagNum--; + + if (TagNum > locus) + memcpy(&TagList[locus], &TagList[locus + 1], + (TagNum - locus) * sizeof(TagItem)); +} + +int +Tagger(time_t chrono, int recno, int mode) +{ + int head, tail, posi = 0, comp; + + 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) + return NA; + + TagNum--; + memcpy(&TagList[posi], &TagList[posi + 1], + (TagNum - posi) * sizeof(TagItem)); + } + else if (TagNum < MAXTAGS) + { + TagItem *tagp, buf[MAXTAGS]; + + tail = (TagNum - head) * sizeof(TagItem); + tagp = &TagList[head]; + memcpy(buf, tagp, tail); + tagp->chrono = chrono; + tagp->recno = recno; + memcpy(++tagp, buf, tail); + TagNum++; + } + else + { + bell(); + return 0; /* full */ + } + return YEA; +} + + +void +EnumTagName( char *fname, int locus) +{ + sprintf(fname, "M.%d.A", (int) TagList[locus].chrono); +} + +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(char *msg) +{ + char buf[80]; + int num; + + num = TagNum; + sprintf(buf, "�� %s A)�峹 T)�аO Q)uit?", msg); + switch (rget(b_lines-1, buf)) + { + case 'q': + num = -1; + break; + case 'a': + num = 0; + } + return num; +} + + +#include <sys/mman.h> + +#define BATCH_SIZE 65536 + +char * +f_map (char *fpath, int *fsize) +{ + int fd, size; + struct stat st; + + 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; + } + + fpath = (char *) mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + close(fd); + *fsize = size; + return fpath; +} + + +static int +TagThread(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) +{ + if (TagNum && ((currstat != READING) || (currmode & MODE_BOARD))) + { + if(getans("�R���Ҧ��аO[N]?") != 'y') + return FULLUPDATE; + delete_range(currdirect, 0, 0); + TagNum = 0; + if(bid>0); + setbtotal(bid); + return NEWDIRECT; + } + return DONOTHING; +} + + +/* ----------------------------------------------------- */ +/* cursor & reading record position control */ +/* ----------------------------------------------------- */ +keeploc_t *getkeep(char *s, int def_topline, int def_cursline) { + static struct keeploc_t *keeplist = NULL; + struct keeploc_t *p; + void *malloc(); + + if(def_cursline >= 0) + for(p = keeplist; p; p = p->next) { + if(!strcmp(s, p->key)) { + if(p->crs_ln < 1) + p->crs_ln = 1; + return p; + } + } + else + def_cursline = -def_cursline; + p = (keeploc_t *)malloc(sizeof(keeploc_t)); + p->key = (char *)malloc(strlen(s) + 1); + strcpy(p->key, s); + p->top_ln = def_topline; + p->crs_ln = def_cursline; + p->next = keeplist; + return (keeplist = p); +} + +void fixkeep(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 top; + + if(val > last_line) { + bell(); + val = last_line; + } + if(val <= 0) { + bell(); + val = 1; + } + + top = locmem->top_ln; + if(val >= top && val < top + p_lines) { + cursor_clear(3 + locmem->crs_ln - top, 0); + locmem->crs_ln = val; + cursor_show(3 + val - top, 0); + return DONOTHING; + } + locmem->top_ln = val - from_top; + if(locmem->top_ln <= 0) + locmem->top_ln = 1; + locmem->crs_ln = val; + return PARTUPDATE; +} + +static int move_cursor_line(keeploc_t *locmem, int mode) { + int top, crs; + int reload = 0; + + top = locmem->top_ln; + crs = locmem->crs_ln; + if(mode == READ_PREV) { + if(crs <= top) { + top -= p_lines - 1; + if(top < 1) + top = 1; + reload = 1; + } + if(--crs < 1) { + crs = 1; + reload = -1; + } + } else if(mode == READ_NEXT) { + if(crs >= top + p_lines - 1) { + top += p_lines - 1; + reload = 1; + } + if(++crs > last_line) { + crs = last_line; + reload = -1; + } + } + locmem->top_ln = top; + locmem->crs_ln = crs; + return reload; +} + +static int thread(keeploc_t *locmem, int stype) { + static char a_ans[32], t_ans[32]; + char ans[32], s_pmt[64]; + register char *tag, *query = NULL; + register int now, pos, match, near = 0; + fileheader_t fh; + int circulate_flag = 1; /* circulate at end or begin */ + + match = hit_thread = 0; + now = pos = locmem->crs_ln; + if(stype == 'A') { + if(!*currowner) + return DONOTHING; + str_lower(a_ans, currowner); + query = a_ans; + circulate_flag = 0; + stype = 0; + } else if(stype == 'a') { + if(!*currowner) + return DONOTHING; + str_lower(a_ans, currowner); + query = a_ans; + circulate_flag = 0; + stype = RS_FORWARD; + } else if(stype == '/') { + if(!*t_ans) + return DONOTHING; + query = t_ans; + circulate_flag = 0; + stype = RS_TITLE | RS_FORWARD; + } else if(stype == '?') { + if(!*t_ans) + return DONOTHING; + circulate_flag = 0; + query = t_ans; + stype = RS_TITLE; + } else if(stype & RS_RELATED) { + tag = headers[pos - locmem->top_ln].title; + if(stype & RS_CURRENT) { + if(stype & RS_FIRST) { + if(!strncmp(currtitle, tag, 40)) + return DONOTHING; + near = 0; + } + query = currtitle; + } else { + query = subject(tag); + if(stype & RS_FIRST) { + if(query == tag) + return DONOTHING; + near = 0; + } + } + } else if(!(stype & RS_THREAD)) { + query = (stype & RS_TITLE) ? t_ans : a_ans; + if(!*query && query == a_ans) { + if(*currowner) + strcpy(a_ans, currowner); + else if (*currauthor) + strcpy(a_ans, currauthor); + } + sprintf(s_pmt, "%s�j�M%s [%s] ",(stype & RS_FORWARD) ? "����":"���e", + (stype & RS_TITLE) ? "���D" : "�@��", query); + getdata(b_lines - 1, 0, s_pmt, ans, 30, DOECHO); + if(*ans) + strcpy(query, ans); + else if(*query == '\0') + return DONOTHING; + } + + tag = fh.owner; + + do { + if(!circulate_flag || stype & RS_RELATED) { + if(stype & RS_FORWARD) { + if(++now > last_line) + return DONOTHING; + } else { + if(--now <= 0) { + if((stype & RS_FIRST) && (near)) { + hit_thread = 1; + return cursor_pos(locmem, near, 10); + } + return DONOTHING; + } + } + } else { + if(stype & RS_FORWARD) { + if(++now > last_line) + now = 1; + } else if(--now <= 0) + now = last_line; + } + + get_record(currdirect, &fh, sizeof(fileheader_t), now); + + if(fh.owner[0] == '-') + continue; + + if(stype & RS_THREAD) { + if(strncasecmp(fh.title, str_reply, 3)) { + hit_thread = 1; + return cursor_pos(locmem, now, 10); + } + continue; + } + + if(stype & RS_TITLE) + tag = subject(fh.title); + + if(((stype & RS_RELATED) && !strncmp(tag, query, 40)) || + (!(stype & RS_RELATED) && ((query == currowner) ? + !strcmp(tag, query) : + strstr_lower(tag, query)))) { + if((stype & RS_FIRST) && tag != fh.title) { + near = now; + continue; + } + + hit_thread = 1; + match = cursor_pos(locmem, now, 10); + if((!(stype & RS_CURRENT)) && + (stype & RS_RELATED) && + strncmp(currtitle, query, 40)) { + strncpy(currtitle, query, 40); + match = PARTUPDATE; + } + break; + } + } while(now != pos); + + return match; +} + + +#ifdef INTERNET_EMAIL +static void mail_forward(fileheader_t *fhdr, char *direct, int mode) { + int i; + char buf[STRLEN]; + char *p; + + strncpy(buf, direct, sizeof(buf)); + if((p = strrchr(buf, '/'))) + *p = '\0'; + switch(i = doforward(buf, fhdr, mode)) { + case 0: + outmsg(msg_fwd_ok); + break; + case -1: + outmsg(msg_fwd_err1); + break; + case -2: + outmsg(msg_fwd_err2); + break; + default: + break; + } + refresh(); + sleep(1); +} +#endif + +extern userec_t cuser; + +static int select_read(keeploc_t *locmem, int sr_mode) { + register char *tag,*query,*temp; + fileheader_t fh; + char fpath[80], genbuf[MAXPATHLEN], buf3[5]; + char static t_ans[TTLEN+1]=""; + char static a_ans[IDLEN+1]=""; + int fd, fr, size = sizeof(fileheader_t); + struct stat st; +/* rocker.011018: make a reference number for process article */ + int reference = 0; + + if((currmode & MODE_SELECT)) + return -1; + if(sr_mode == RS_TITLE) + query = subject(headers[locmem->crs_ln - locmem->top_ln].title); + else if(sr_mode == RS_NEWPOST) + { + strcpy(buf3, "Re: "); + query = buf3; + } + else + { + char buff[80]; + + query = (sr_mode == RS_RELATED) ? t_ans : a_ans; + sprintf(buff, "�j�M%s [%s] ", + (sr_mode == RS_RELATED) ? "���D" : "�@��", query); + getdata(b_lines, 0,buff, query, 30, DOECHO); + if(!(*query)) + return DONOTHING; + } + + if((fd = open(currdirect, O_RDONLY, 0)) != -1) { + sprintf(genbuf,"SR.%s",cuser.userid); + if(currstat==RMAIL) + sethomefile(fpath,cuser.userid,genbuf); + else + setbfile(fpath,currboard,genbuf); + if(((fr = open(fpath,O_WRONLY | O_CREAT | O_TRUNC,0600)) != -1)) { + switch(sr_mode) { + case RS_TITLE: + while(read(fd,&fh,size) == size) { + ++reference; + tag = subject(fh.title); + if(!strncmp(tag, query, 40)) + { + fh.money = reference | FHR_REFERENCE; + write(fr,&fh,size); + } + } + break; + case RS_RELATED: + while(read(fd,&fh,size) == size) { + ++reference; + tag = fh.title; + if(strcasestr(tag,query)) + { + fh.money = reference | FHR_REFERENCE; + write(fr,&fh,size); + } + } + break; + case RS_NEWPOST: + while(read(fd, &fh, size) == size) { + ++reference; + tag = fh.title; + temp = strstr(tag, query); + if(temp == NULL || temp != tag) + { + write(fr, &fh, size); + fh.money = reference | FHR_REFERENCE; + } + } + case RS_AUTHOR: + while(read(fd,&fh,size) == size) { + ++reference; + tag = fh.owner; + if(strcasestr(tag,query)) + { + write(fr,&fh,size); + fh.money = reference | FHR_REFERENCE; + } + } + break; + } + fstat(fr,&st); + close(fr); + } + close(fd); + if(st.st_size) { + currmode |= MODE_SELECT; + strcpy(currdirect,fpath); + } + } + return st.st_size; +} + +extern userec_t xuser; + +static int i_read_key(onekey_t *rcmdlist, keeploc_t *locmem, int ch, int bid) { + int i, mode = DONOTHING; + + switch(ch) { + case 'q': + case 'e': + case KEY_LEFT: + return (currmode & MODE_SELECT) ? board_select() : + (currmode & MODE_ETC) ? board_etc() : + (currmode & MODE_DIGEST) ? board_digest() : DOQUIT; + case Ctrl('L'): + redoscr(); + break; +/* + case Ctrl('C'): + cal(); + return FULLUPDATE; + break; +*/ + case KEY_ESC: + if(KEY_ESC_arg == 'i') { + t_idle(); + return FULLUPDATE; + } + break; + case Ctrl('H'): + if(select_read(locmem, RS_NEWPOST)) + return NEWDIRECT; + else + return READ_REDRAW; + case 'a': + case 'A': + if(select_read(locmem,RS_AUTHOR)) + return NEWDIRECT; + else + return READ_REDRAW; + case '/': + case '?': + if(select_read(locmem,RS_RELATED)) + return NEWDIRECT; + else + return READ_REDRAW; + case 'S': + if(select_read(locmem,RS_TITLE)) + return NEWDIRECT; + else + return READ_REDRAW; + /* quick search title first */ + case '=': + return thread(locmem, RELATE_FIRST); + case '\\': + return thread(locmem, CURSOR_FIRST); + /* quick search title forword */ + case ']': + return thread(locmem, RELATE_NEXT); + case '+': + return thread(locmem, CURSOR_NEXT); + /* quick search title backword */ + case '[': + return thread(locmem, RELATE_PREV); + case '-': + return thread(locmem, CURSOR_PREV); + case '<': + case ',': + return thread(locmem, THREAD_PREV); + case '.': + case '>': + return thread(locmem, THREAD_NEXT); + case 'p': + case 'k': + case KEY_UP: + return cursor_pos(locmem, locmem->crs_ln - 1, p_lines - 2); + case 'n': + case 'j': + case KEY_DOWN: + return cursor_pos(locmem, locmem->crs_ln + 1, 1); + case ' ': + case KEY_PGDN: + case 'N': + case Ctrl('F'): + if(last_line >= locmem->top_ln + p_lines) { + if(last_line > locmem->top_ln + p_lines) + locmem->top_ln += p_lines; + else + locmem->top_ln += p_lines - 1; + locmem->crs_ln = locmem->top_ln; + return PARTUPDATE; + } + cursor_clear(3 + locmem->crs_ln - locmem->top_ln, 0); + locmem->crs_ln = last_line; + cursor_show(3 + locmem->crs_ln - locmem->top_ln, 0); + break; + case KEY_PGUP: + case Ctrl('B'): + case 'P': + if(locmem->top_ln > 1) { + locmem->top_ln -= p_lines; + if(locmem->top_ln <= 0) + locmem->top_ln = 1; + locmem->crs_ln = locmem->top_ln; + return PARTUPDATE; + } + break; + case KEY_END: + case '$': + if(last_line >= locmem->top_ln + p_lines) { + locmem->top_ln = last_line - p_lines + 1; + if(locmem->top_ln <= 0) + locmem->top_ln = 1; + locmem->crs_ln = last_line; + return PARTUPDATE; + } + cursor_clear(3 + locmem->crs_ln - locmem->top_ln, 0); + locmem->crs_ln = last_line; + cursor_show(3 + locmem->crs_ln - locmem->top_ln, 0); + break; + case 'F': + case 'U': + if(HAS_PERM(PERM_FORWARD)) { + mail_forward(&headers[locmem->crs_ln - locmem->top_ln], + currdirect, ch /*== 'U'*/); + /*by CharlieL*/ + return FULLUPDATE; + } + break; + case Ctrl('Q'): + return my_query(headers[locmem->crs_ln - locmem->top_ln].owner); + case Ctrl('S'): + if(HAS_PERM(PERM_ACCOUNTS)) { + int id; + userec_t muser; + + strcpy(currauthor, headers[locmem->crs_ln - locmem->top_ln].owner); + stand_title("�ϥΪ̳]�w"); + move(1, 0); + if((id = getuser(headers[locmem->crs_ln - locmem->top_ln].owner))){ + memcpy(&muser, &xuser, sizeof(muser)); + user_display(&muser, 1); + uinfo_query(&muser, 1, id); + } + return FULLUPDATE; + } + break; + +/* rocker.011018: �ĥηs��tag�Ҧ� */ + case 't': +/* 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].money & ~FHR_REFERENCE) : + locmem->crs_ln, TAG_TOGGLE)) + return POS_NEXT; + return DONOTHING; + + case Ctrl('C'): + if (TagNum) + { + TagNum = 0; + return FULLUPDATE; + } + return DONOTHING; + + case Ctrl('T'): + return TagThread(currdirect); + case Ctrl('D'): + return TagPruner(bid); + case '\n': + case '\r': + case 'l': + case KEY_RIGHT: + ch = 'r'; + default: + for(i = 0; rcmdlist[i].fptr; i++) { + if(rcmdlist[i].key == ch) { + mode = (*(rcmdlist[i].fptr))(locmem->crs_ln, + &headers[locmem->crs_ln - + locmem->top_ln], currdirect); + break; + } + if(rcmdlist[i].key == 'h') + if(currmode & (MODE_ETC | MODE_DIGEST)) + return DONOTHING; + } + } + return mode; +} + +void i_read(int cmdmode, char *direct, void (*dotitle)(), void (*doentry)(), onekey_t *rcmdlist, int bidcache) { + keeploc_t *locmem = NULL; + int recbase = 0, mode, ch; + int num = 0, entries = 0; + int i; + int jump = 0; + char genbuf[4]; + char currdirect0[64]; + int last_line0 = last_line; + int hit_thread0 = hit_thread; + fileheader_t *headers0 = headers; + + strcpy(currdirect0 ,currdirect); +#define FHSZ sizeof(fileheader_t) +// Ptt:�o��headers �i�H�w��ݪO���̫�60�g��cache + headers = (fileheader_t *)calloc(p_lines, FHSZ); + strcpy(currdirect, direct); + mode = NEWDIRECT; + +/* rocker.011018: �[�J�s��tag���� */ + TagNum = 0; + + do { + /* �̾� mode ��� fileheader */ + setutmpmode(cmdmode); + switch(mode) { + case NEWDIRECT: /* �Ĥ@�����J���ؿ� */ + case DIRCHANGED: + if(bidcache>0 && !(currmode & (MODE_SELECT| MODE_DIGEST)) ) + last_line=getbtotal(currbid); + else + last_line= get_num_records(currdirect, FHSZ); + + if(mode == NEWDIRECT) { + if(last_line == 0) { + if(curredit & EDIT_ITEM) { + outs("�S�����~"); + refresh(); + goto return_i_read; + } else if(curredit & EDIT_MAIL) { + outs("�S���ӫH"); + refresh(); + goto return_i_read; + } else if(currmode & MODE_ETC) { + board_etc(); /* Kaede */ + outmsg("�|�������䥦�峹"); + refresh(); + } else if(currmode & MODE_DIGEST) { + board_digest(); /* Kaede */ + outmsg("�|��������K"); + refresh(); + } else if(currmode & MODE_SELECT) { + board_select(); /* Leeym */ + outmsg("�S�����t�C���峹"); + refresh(); + } else { + getdata(b_lines - 1, 0, + "�ݪO�s���� (P)�o���峹 (Q)���}�H[Q] ", + genbuf, 4, LCECHO); + if(genbuf[0] == 'p') + do_post(); + goto return_i_read; + } + } + num = last_line - p_lines + 1; + locmem = getkeep(currdirect, num < 1 ? 1 : num, last_line); + } + recbase = -1; + + case FULLUPDATE: + (*dotitle)(); + + case PARTUPDATE: + if(last_line < locmem->top_ln + p_lines) { + if(bidcache>0 && !(currmode & (MODE_SELECT| MODE_DIGEST))) + num=getbtotal(currbid); + else + num = get_num_records(currdirect, FHSZ); + + if(last_line != num) { + last_line = num; + recbase = -1; + } + } + + if(last_line == 0) + goto return_i_read; + else 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(bidcache>0 && !(currmode & (MODE_SELECT| MODE_DIGEST)) + && (last_line - recbase) < DIRCACHESIZE ) + entries = get_fileheader_cache(currbid, currdirect, headers, + recbase, p_lines); + else + entries = get_records(currdirect, headers, FHSZ, recbase, + p_lines); + } + if(locmem->crs_ln > last_line) + locmem->crs_ln = last_line; + move(3, 0); + clrtobot(); + case PART_REDRAW: + move(3, 0); + for (i = 0; i < entries; i++) + (*doentry) (locmem->top_ln + i, &headers[i]); + case READ_REDRAW: + outmsg(curredit & EDIT_ITEM ? + "\033[44m �p�H���� \033[30;47m �~��? \033[m" : + curredit & EDIT_MAIL ? msg_mailer : MSG_POSTER); + break; + case READ_PREV: + case READ_NEXT: + case RELATE_PREV: + case RELATE_NEXT: + case RELATE_FIRST: + case POS_NEXT: + case 'A': + case 'a': + case '/': + case '?': + jump = 1; + break; + } + + /* Ū����L�A�[�H�B�z�A�]�w mode */ + if(!jump) { + cursor_show(3 + locmem->crs_ln - locmem->top_ln, 0); + ch = egetch(); + mode = DONOTHING; + } else + ch = ' '; + + if(mode == POS_NEXT) { + mode = cursor_pos(locmem, locmem->crs_ln + 1, 1); + if(mode == DONOTHING) + mode = PART_REDRAW; + jump = 0; + } else if(ch >= '0' && ch <= '9') { + if((i = search_num(ch, last_line)) != -1) + mode = cursor_pos(locmem, i + 1, 10); + } else { + if(!jump) + mode = i_read_key(rcmdlist, locmem, ch, currbid); + while(mode == READ_NEXT || mode == READ_PREV || + mode == RELATE_FIRST || mode == RELATE_NEXT || + mode == RELATE_PREV || mode == THREAD_NEXT || + mode == THREAD_PREV || mode == 'A' || mode == 'a' || + mode == '/' || mode == '?') { + int reload; + + if(mode == READ_NEXT || mode == READ_PREV) + reload = move_cursor_line(locmem, mode); + else { + reload = thread(locmem, mode); + if(!hit_thread) { + mode = FULLUPDATE; + break; + } + } + + if(reload == -1) { + mode = FULLUPDATE; + break; + } else if(reload) { + recbase = locmem->top_ln; + + if(bidcache>0 && !(currmode &(MODE_SELECT| MODE_DIGEST)) + && last_line-recbase<DIRCACHESIZE ) + entries = get_fileheader_cache(currbid, currdirect, + headers, recbase, p_lines); + else + entries = get_records(currdirect, headers, FHSZ, recbase, + p_lines); + + if(entries <= 0) { + last_line = -1; + break; + } + } + num = locmem->crs_ln - locmem->top_ln; + if(headers[num].owner[0] != '-') + mode = i_read_key(rcmdlist, locmem, ch, bidcache); + } + } + } while(mode != DOQUIT); +#undef FHSZ + + return_i_read: + free(headers); + last_line = last_line0; + hit_thread = hit_thread0; + headers = headers0; + strcpy(currdirect ,currdirect0); + return; +} diff --git a/mbbsd/record.c b/mbbsd/record.c new file mode 100644 index 00000000..59bc6a75 --- /dev/null +++ b/mbbsd/record.c @@ -0,0 +1,536 @@ +/* $Id: record.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "proto.h" + +#undef HAVE_MMAP +#define BUFSIZE 512 + +extern char *str_reply; + +static void PttLock(int fd, int size, int mode) { + static struct flock lock_it; + int ret; + + lock_it.l_whence = SEEK_CUR; /* from current point */ + lock_it.l_start = 0; /* -"- */ + lock_it.l_len = size; /* length of data */ + lock_it.l_type = mode; /* set exclusive/write lock */ + lock_it.l_pid = 0; /* pid not actually interesting */ + while((ret = fcntl(fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR); +} + +#define safewrite write + +int get_num_records(char *fpath, int size) { + struct stat st; + if(stat(fpath, &st) == -1) + return 0; + return st.st_size / size; +} + +int get_sum_records(char* fpath, int size) { + struct stat st; + long ans = 0; + FILE* fp; + fileheader_t fhdr; + char buf[200], *p; + + if(!(fp = fopen(fpath, "r"))) + return -1; + + strcpy(buf, fpath); + p = strrchr(buf, '/') + 1; + + while(fread(&fhdr, size, 1, fp) == 1) { + strcpy(p, fhdr.filename); + 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(char *fpath, void *rptr, int size, int id) { + int fd = -1; + + 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(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(char *fpath, void *rptr, int size, int id) { + int fd; + + if(id < 1 || (fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) + return -1; + + lseek(fd, (off_t) (size * (id - 1)), SEEK_SET); + PttLock(fd, size, F_WRLCK); + safewrite(fd, rptr, size); + PttLock(fd, size, F_UNLCK); + close(fd); + + return 0; +} + +/* rocker.011022: �קKlock�ɶ}�Үɤ����`�_�u,�y���ä[lock */ +static int +force_open (char *fname) +{ + int fd; + time_t expire; + + expire = time(NULL) - 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; +} + + +#if !defined(_BBS_UTIL_C_) +/* new/old/lock file processing */ +typedef struct nol_t { + char newfn[256]; + char oldfn[256]; + char lockfn[256]; +} nol_t; + +static void nolfilename(nol_t *n, char *fpath) { + sprintf(n->newfn, "%s.new", fpath); + sprintf(n->oldfn, "%s.old", fpath); + sprintf(n->lockfn, "%s.lock", fpath); +} + +int delete_record(char fpath[], int size, int id) { + nol_t my; + char abuf[BUFSIZE]; + int fdr, fdw, fd; + int count; + + 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) { + move(10,10); + outs("delete_record failed!!! (open)"); + pressanykey(); + 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)) { + flock(fd, LOCK_UN); + close(fd); + close(fdr); + return -1; + } + count = 1; + while(read(fdr, abuf, size) == size) { + if(id != count++ && (safewrite(fdw, abuf, size) == -1)) { + unlink(my.newfn); + close(fdr); + close(fdw); + flock(fd, LOCK_UN); + close(fd); + return -1; + } + } + 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 0; +} + +static char *title_body(char *title) { + if(!strncasecmp(title, str_reply, 3)) { + title += 3; + if(*title == ' ') + title++; + } + return title; +} + +int delete_range(char *fpath, int id1, int id2) { + fileheader_t fhdr; + nol_t my; + char fullpath[STRLEN], *t; + int fdr, fdw, fd; + int count; + extern int Tagger(); + + 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; + strcpy(fullpath, fpath); + t = strrchr(fullpath, '/') + 1; + + 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) || /* ��K */ + (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); + } + ++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 0; +} + +int search_rec(char* dirname, int (*filecheck)()) { + fileheader_t fhdr; + FILE *fp; + int ans = 0; + + if(!(fp = fopen(dirname, "r"))) + return 0; + + while(fread(&fhdr, sizeof(fhdr), 1, fp)) { + ans++; + if((*filecheck) (&fhdr)) { + fclose(fp); + return ans; + } + } + fclose(fp); + return 0; +} + +int delete_files(char* dirname, int (*filecheck)(), int record) { + fileheader_t fhdr; + FILE *fp, *fptmp; + int ans = 0; + char tmpfname[128]; + char genbuf[256]; + char deleted[256]; + fileheader_t delfh; + char deletedDIR[] = "boards/deleted/.DIR"; + + strcpy(deleted, "boards/deleted"); + + if(!(fp = fopen(dirname, "r"))) + return ans; + + strcpy(tmpfname, dirname); + strcat(tmpfname, "_tmp"); + + if(!(fptmp = fopen(tmpfname, "w"))) { + fclose(fp); + return ans; + } + + while(fread(&fhdr, sizeof(fhdr), 1, fp)){ + if((*filecheck)(&fhdr)) { + ans++; + setdirpath(genbuf, dirname, fhdr.filename); + if (record){ + deleted[14] = '\0'; + stampfile(deleted, &delfh); + strcpy(delfh.owner, fhdr.owner); + strcpy(delfh.title, fhdr.title); + Link(genbuf, deleted); + append_record(deletedDIR, &delfh, sizeof(delfh)); + } + unlink(genbuf); + } else + fwrite(&fhdr, sizeof(fhdr), 1, fptmp); + } + + fclose(fp); + fclose(fptmp); + unlink(dirname); + Rename(tmpfname, dirname); + + return ans; +} + +int delete_file(char *dirname, int size, int ent, int (*filecheck)()) { + char abuf[BUFSIZE]; + int fd; + struct stat st; + long numents; + + if(ent < 1 || (fd = open(dirname, O_RDWR)) == -1) + return -1; + flock(fd, LOCK_EX); + fstat(fd, &st); + numents = ((long) st.st_size) / size; + if(((long) st.st_size) % size) + fprintf(stderr, "align err\n"); + if(lseek(fd, (off_t) size * (ent - 1), SEEK_SET) != -1) { + if(read(fd, abuf, size) == size){ + if((*filecheck) (abuf)) { + int i; + + for(i = ent; i < numents; i++) { + if(lseek(fd, (off_t)((i) * size), SEEK_SET) == -1 || + read(fd, abuf, size) != size || + lseek(fd, (off_t)(i - 1) * size, SEEK_SET) == -1) + break; + if(safewrite(fd, abuf, size) != size) + break; + } + ftruncate(fd, (off_t) size * (numents - 1)); + flock(fd, LOCK_UN); + close(fd); + return 0; + } + } + } + lseek(fd, 0, SEEK_SET); + ent = 1; + while(read(fd, abuf, size) == size) { + if((*filecheck)(abuf)) { + int i; + + for(i = ent; i < numents; i++) { + if(lseek(fd, (off_t) (i + 1) * size, SEEK_SET) == -1 || + read(fd, abuf, size) != size || + lseek(fd, (off_t) (i) * size, SEEK_SET) == -1 || + safewrite(fd, abuf, size) != size) + break; + } + ftruncate(fd, (off_t) size * (numents - 1)); + flock(fd, LOCK_UN); + close(fd); + return 0; + } + ent++; + } + flock(fd, LOCK_UN); + close(fd); + return -1; +} + +#endif /* !defined(_BBS_UTIL_C_) */ + +int apply_record(char *fpath, int (*fptr)(), int size) { + char abuf[BUFSIZE]; + FILE* fp; + + if(!(fp = fopen(fpath, "r"))) + return -1; + + while(fread(abuf, 1, size, fp) == size) + if((*fptr) (abuf) == QUIT) { + fclose(fp); + return QUIT; + } + fclose(fp); + return 0; +} + +/* mail / post �ɡA�̾ڮɶ��إ��ɮסA�[�W�l�W */ +int stampfile(char *fpath, fileheader_t *fh) { + register char *ip = fpath; + time_t dtime; + struct tm *ptime; + int fp = 0; + + if(access(fpath, X_OK | R_OK | W_OK)) + mkdir(fpath, 0755); + + time(&dtime); + while (*(++ip)); + *ip++ = '/'; + do { + sprintf(ip, "M.%ld.A", ++dtime ); + if(fp == -1 && errno != EEXIST) + return -1; + } while((fp = open(fpath, O_CREAT | O_EXCL | O_WRONLY, 0644)) == -1); + close(fp); + memset(fh, 0, sizeof(fileheader_t)); + strcpy(fh->filename, ip); + ptime = localtime(&dtime); + sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); + return 0; +} + +void stampdir(char *fpath, fileheader_t *fh) { + register char *ip = fpath; + time_t dtime; + struct tm *ptime; + + if(access(fpath, X_OK | R_OK | W_OK)) + mkdir(fpath, 0755); + + time(&dtime); + while(*(++ip)); + *ip++ = '/'; + do { + sprintf(ip, "D%lX", ++dtime & 07777); + } while(mkdir(fpath, 0755) == -1); + memset(fh, 0, sizeof(fileheader_t)); + strcpy(fh->filename, ip); + ptime = localtime(&dtime); + sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); +} + +void stamplink(char *fpath, fileheader_t *fh) { + register char *ip = fpath; + time_t dtime; + struct tm *ptime; + + if(access(fpath, X_OK | R_OK | W_OK)) + mkdir(fpath, 0755); + + time(&dtime); + while(*(++ip)); + *ip++ = '/'; + do { + sprintf(ip, "S%lX", ++dtime ); + } while(symlink("temp", fpath) == -1); + memset(fh, 0, sizeof(fileheader_t)); + strcpy(fh->filename, ip); + ptime = localtime(&dtime); + sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); +} + +int do_append(char *fpath, fileheader_t *record, int size) { + int fd; + + if((fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) { + perror("open"); + return -1; + } + flock(fd, LOCK_EX); + lseek(fd, 0, SEEK_END); + + safewrite(fd, record, size); + + flock(fd, LOCK_UN); + close(fd); + return 0; +} + +int append_record(char *fpath, fileheader_t *record, int size) { +#if !defined(_BBS_UTIL_C_) + int m,n; + if(get_num_records(fpath, sizeof(fileheader_t)) <= MAX_KEEPMAIL * 2) { + FILE *fp; + char buf[512],address[200]; + + for(n = strlen(fpath) - 1 ; fpath[n] != '/' && n > 0; n--); + strncpy(buf, fpath, n + 1); + buf[n + 1] = 0; + for(m = strlen(buf) - 2 ; buf[m] != '/' && m > 0 ; m--); + strcat(buf, ".forward"); + if((fp = fopen(buf,"r"))) { + fscanf(fp,"%s",address); + fclose(fp); + if(buf[0] != 0 && buf[0] != ' ') { + buf[n + 1] = 0; + strcat(buf, record->filename); + do_append(fpath,record,size); +#ifndef USE_BSMTP + bbs_sendmail(buf,record->title,address); +#else + bsmtp(buf, record->title, address, 0); +#endif + return 0; + } + } + } +#endif + + do_append(fpath,record,size); + + return 0; +} diff --git a/mbbsd/register.c b/mbbsd/register.c new file mode 100644 index 00000000..e9c25be5 --- /dev/null +++ b/mbbsd/register.c @@ -0,0 +1,339 @@ +/* $Id: register.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#define _XOPEN_SOURCE + +#include <stdio.h> +#include <strings.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "proto.h" + +extern char *str_new; +extern char *msg_uid; +extern int t_lines, t_columns; /* Screen size / width */ +extern char *str_mail_address; + +/* password encryption */ +static char pwbuf[14]; + +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; + } + strcpy(pwbuf, pw); + return crypt(pwbuf, saltc); + } + return ""; +} + +int checkpasswd(char *passwd, char *test) { + char *pw; + + strncpy(pwbuf, test, 14); + pw = crypt(pwbuf, passwd); + return (!strncmp(pw, passwd, 14)); +} + +/* �ˬd user ���U���p */ +int bad_user_id(char *userid) { + int len, i; + len = strlen(userid); + + if(len < 2) + return 1; + + if (not_alpha(userid[0])) + return 1; + for (i=1; i<len; i++) //DickG:�ץ��F�u��� userid �Ĥ@�Ӧr���� bug + if(not_alnum(userid[i])) + return 1; + + if(strcasecmp(userid, str_new) == 0) + return 1; + + /* while((ch = *(++userid))) + if(not_alnum(ch)) + return 1;*/ + return 0; +} + +/* -------------------------------- */ +/* New policy for allocate new user */ +/* (a) is the worst user currently */ +/* (b) is the object to be compared */ +/* -------------------------------- */ +static int compute_user_value(userec_t *urec, time_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 */ + 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,userec_t *urec) +{ + userec_t zerorec; + time_t now=time(NULL); + char genbuf[200],genbuf2[200]; + int val; + if((val = compute_user_value(urec, now)) < 0) { + sprintf(genbuf, "#%d %-12s %15.15s %d %d %d", + uid, urec->userid, ctime(&(urec->lastlogin)) + 4, + urec->numlogins, urec->numposts, val); + if(val > -1 * 60 * 24 * 365) { + memset(&zerorec, 0, sizeof(zerorec)); + log_usies("CLEAN", genbuf); + sprintf(genbuf, "home/%c/%s", urec->userid[0], + urec->userid); + sprintf(genbuf2, "tmp/%s", urec->userid); + if(dashd(genbuf) && Rename(genbuf, genbuf2)) { + sprintf(genbuf, "/bin/rm -fr home/%c/%s >/dev/null 2>&1", + urec->userid[0],urec->userid); + system(genbuf); + } + passwd_update(uid, &zerorec); + remove_from_uhash(uid - 1); + add_to_uhash(uid - 1, ""); + } + else + { + val=0; + log_usies("DATED", genbuf); + } + } + return val; +} + +extern char *fn_passwd; + +int getnewuserid() { + char genbuf[50]; + static char *fn_fresh = ".fresh"; + userec_t utmp,zerorec; + time_t clock; + struct stat st; + int fd, i; + + memset(&zerorec, 0, sizeof(zerorec)); + clock = time(NULL); + + /* Lazy method : ����M�w�g�M�����L���b�� */ + if((i = searchnewuser(0)) == 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(i = 2; i <= MAX_USERS; i++) { + passwd_query(i, &utmp); + check_and_expire_account(i,&utmp); + } + } + } + + passwd_lock(); + i = searchnewuser(1); + if((i <= 0) || (i > MAX_USERS)) { + passwd_unlock(); + if(more("etc/user_full", NA) == -1) + fprintf(stdout, "��p�A�ϥΪ̱b���w�g���F�A�L�k���U�s���b��\n\r"); + safe_sleep(2); + exit(1); + } + + sprintf(genbuf, "uid %d", i); + log_usies("APPLY", genbuf); + + strcpy(zerorec.userid, str_new); + zerorec.lastlogin = clock; + passwd_update(i, &zerorec); + setuserid(i, zerorec.userid); + passwd_unlock(); + return i; +} + +void new_register() { + extern userec_t xuser; + userec_t newuser; + char passbuf[STRLEN]; + int allocid, try, id; + + memset(&newuser, 0, sizeof(newuser)); + more("etc/register", NA); + try = 0; + while(1) { + if(++try >= 6) { + outs("\n�z���տ��~����J�Ӧh�A�ФU���A�ӧa\n"); + refresh(); + + pressanykey(); + oflush(); + exit(1); + } + getdata(17, 0, msg_uid, newuser.userid, IDLEN + 1, DOECHO); + + if(bad_user_id(newuser.userid)) + outs("�L�k�����o�ӥN���A�Шϥέ^��r���A�åB���n�]�t�Ů�\n"); + else if ((id=getuser(newuser.userid)) && + (id=check_and_expire_account(id,&xuser))>=0) + { + if(id==999999) + outs("���N���w�g���H�ϥ� �O��������"); + else + { + sprintf(passbuf,"���N���w�g���H�ϥ� �٦�%d�Ѥ~�L�� \n",id/(60*24)); + outs(passbuf); + } + } + else + break; + } + + try = 0; + while(1) { + if(++try >= 6) { + outs("\n�z���տ��~����J�Ӧh�A�ФU���A�ӧa\n"); + refresh(); + + pressanykey(); + oflush(); + exit(1); + } + if((getdata(19, 0, "�г]�w�K�X�G", passbuf, PASSLEN, NOECHO) < 3) || + !strcmp(passbuf, newuser.userid)) { + outs("�K�X��²��A���D�J�I�A�ܤ֭n 4 �Ӧr�A�Э��s��J\n"); + continue; + } + strncpy(newuser.passwd, passbuf, PASSLEN); + getdata(20, 0, "���ˬd�K�X�G", passbuf, PASSLEN, NOECHO); + if(strncmp(passbuf, newuser.passwd, PASSLEN)) { + outs("�K�X��J���~, �Э��s��J�K�X.\n"); + continue; + } + passbuf[8] = '\0'; + strncpy(newuser.passwd, genpasswd(passbuf), PASSLEN); + break; + } + newuser.userlevel = PERM_DEFAULT; + newuser.uflag = COLOR_FLAG | BRDSORT_FLAG | MOVIE_FLAG; + newuser.firstlogin = newuser.lastlogin = time(NULL); + newuser.money = 0; + newuser.pager = 1; + allocid = getnewuserid(); + if(allocid > MAX_USERS || allocid <= 0) { + fprintf(stderr, "�����H�f�w�F���M�I\n"); + exit(1); + } + + if(passwd_update(allocid, &newuser) == -1) { + fprintf(stderr, "�Ⱥ��F�A�A���I\n"); + exit(1); + } + setuserid(allocid, newuser.userid); + if(!dosearchuser(newuser.userid)) { + fprintf(stderr, "�L�k�إ߱b��\n"); + exit(1); + } +} + +extern userec_t cuser; + +void check_register() { + char *ptr = NULL; + + stand_title("�иԲӶ�g�ӤH���"); + + while(strlen(cuser.username) < 2) + getdata(2, 0, "�︹�ʺ١G", cuser.username, 24, DOECHO); + + for(ptr = cuser.username; *ptr; ptr++) { + if (*ptr == 9) /* TAB convert */ + *ptr = ' '; + } + while(strlen(cuser.realname) < 4) + getdata(4, 0, "�u��m�W�G", cuser.realname, 20, DOECHO); + + while(strlen(cuser.address) < 8) + getdata(6, 0, "�p���a�}�G", cuser.address, 50, DOECHO); + + + if(!strchr(cuser.email, '@')) { + bell(); + move(t_lines - 4, 0); + prints("�� ���F�z���v�q�A�ж�g�u�ꪺ E-mail address�A " + "�H��T�{�դU�����A\n" + "�榡�� \033[44muser@domain_name\033[0m �� \033[44muser" + "@\\[ip_number\\]\033[0m�C\n\n" + "�� �p�G�z�u���S�� E-mail�A�Ъ����� [return] �Y�i�C"); + + do { + getdata(8, 0, "�q�l�H�c�G", cuser.email, 50, DOECHO); + if(!cuser.email[0]) + sprintf(cuser.email, "%s%s", cuser.userid, str_mail_address); + } while(!strchr(cuser.email, '@')); + + } + if(!HAS_PERM(PERM_SYSOP) && !HAS_PERM(PERM_LOGINOK)) { + /* �^�йL�����{�ҫH��A�δ��g E-mail post �L */ + clear(); + move(9,3); + prints("�иԶ�g\033[32m���U�ӽг�\033[m�A" + "�q�i�����H��o�i���ϥ��v�O�C\n\n\n\n"); + u_register(); + } + +#ifdef NEWUSER_LIMIT + if(!(cuser.userlevel & PERM_LOGINOK) && !HAS_PERM(PERM_SYSOP)) { + if(cuser.lastlogin - cuser.firstlogin < 3 * 86400) + cuser.userlevel &= ~PERM_POST; + more("etc/newuser", YEA); + } +#endif +} diff --git a/mbbsd/screen.c b/mbbsd/screen.c new file mode 100644 index 00000000..46ad5b38 --- /dev/null +++ b/mbbsd/screen.c @@ -0,0 +1,559 @@ +/* $Id: screen.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +extern int t_lines, t_columns; /* Screen size / width */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern int showansi; + +extern char *clearbuf; +extern char *cleolbuf; +extern char *scrollrev; +extern char *strtstandout; +extern char *endstandout; +extern int clearbuflen; +extern int cleolbuflen; +extern int scrollrevlen; +extern int strtstandoutlen; +extern int endstandoutlen; +extern int automargins; +#ifdef SUPPORT_GB +static int current_font_type=TYPE_BIG5; +static int gbinited=0; +#endif +#define SCR_WIDTH 80 +#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) + +unsigned char scr_lns, scr_cols; +static unsigned char cur_ln = 0, cur_col = 0; +static unsigned char docls, downfrom = 0; +static unsigned char standing = NA; +static char roll = 0; +static int scrollcnt, tc_col, tc_line; + +screenline_t *big_picture = NULL; + +#define MODIFIED (1) /* if line has been modifed, screen output */ +#define STANDOUT (2) /* if this line has a standout region */ + +int tputs(const char *str, int affcnt, int (*putc)(int)); + +void initscr() { + if(!big_picture) { + scr_lns = t_lines; + scr_cols = t_columns = ANSILINELEN; + /* scr_cols = MIN(t_columns, ANSILINELEN); */ + big_picture = (screenline_t *) calloc(scr_lns, sizeof(screenline_t)); + docls = YEA; + } +} + +void move(int y, int x) { + cur_col = x; + cur_ln = y; +} + +void getyx(int *y, int *x) { + *y = cur_ln; + *x = cur_col; +} + +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(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 redoscr() { + register screenline_t *bp; + register int i, j, 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); + if(bp->mode & STANDOUT) + standoutput(bp->data, 0, len, bp->sso, bp->eso); + else + output(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(); +} + +void refresh() { + register screenline_t *bp = big_picture; + register int i, j, len; + extern int automargins; + extern int scrollrevlen; + if(num_in_buf()) + return; + + if((docls) || (abs(scrollcnt) >= (scr_lns - 3))) { + redoscr(); + return; + } + + if(scrollcnt < 0) { + if(!scrollrevlen) { + redoscr(); + 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); + if(bp->emod >= len) + bp->emod = len - 1; + rel_move(tc_col, tc_line, bp->smod, i); + + if(bp->mode & STANDOUT) + standoutput(bp->data, bp->smod, bp->emod + 1, + bp->sso, bp->eso); + else + output(&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; + if(++tc_line >= t_lines) + tc_line = b_lines; + } else + tc_col = t_columns - 1; + } + } + + if(bp->oldlen > len) { + 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() { + register screenline_t *slp; + + register int i; + + docls = YEA; + cur_col = cur_ln = roll = downfrom = i = 0; + do { + slp = &big_picture[i]; + slp->mode = slp->len = slp->oldlen = 0; + } while(++i < scr_lns); +} + +void clrtoeol() { + register screenline_t *slp; + register int ln; + + standing = NA; + if((ln = cur_ln + roll) >= scr_lns) + ln -= scr_lns; + slp = &big_picture[ln]; + if(cur_col <= slp->sso) + slp->mode &= ~STANDOUT; + + 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 clrtoline(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 = 255; + } +} + +void clrtobot() { + clrtoline(scr_lns); +} + +void outch(unsigned char c) { + register screenline_t *slp; + register int i; + + if((i = cur_ln + roll) >= scr_lns) + i -= scr_lns; + slp = &big_picture[i]; + + 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 != '\033' && !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) != 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 (++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++; + } + +} + +static void parsecolor(char *buf) { + char *val; + char data[24]; + + data[0] = '\0'; + val = (char *)strtok(buf, ";"); + + while(val) { + if(atoi(val) < 30) { + if(data[0]) + strcat(data, ";"); + strcat(data, val); + } + val = (char *) strtok(NULL, ";"); + } + strcpy(buf, data); +} + +#define NORMAL (00) +#define ESCAPE (01) +#define VTKEYS (02) + +void outc(unsigned char ch) { + if(showansi) + outch(ch); + else { + static char buf[24]; + static int p = 0; + static int mode = NORMAL; + int i; + + switch(mode) { + case NORMAL: + if(ch == '\033') + mode = ESCAPE; + else + outch(ch); + return; + case ESCAPE: + if(ch == '[') + mode = VTKEYS; + else { + mode = NORMAL; + outch(''); + outch(ch); + } + return; + case VTKEYS: + if(ch == 'm') { + buf[p++] = '\0'; + parsecolor(buf); + } else if((p < 24) && (not_alpha(ch))) { + buf[p++] = ch; + return; + } + if(buf[0]) { + outch(''); + outch('['); + + for(i = 0; (p = buf[i]); i++) + outch(p); + outch(ch); + } + p = 0; + mode = NORMAL; + } + } +} + +static void do_outs(char *str) { + while(*str) + { + outc(*str++); + } +} +#ifdef SUPPORT_GB +static void gb_init() +{ + if(current_font_type == TYPE_GB) + { + hc_readtab(BBSHOME"/etc/hc.tab"); + } + gbinited = 1; +} + +static void gb_outs(char *str) +{ + do_outs(hc_convert_str(str, HC_BIGtoGB, HC_DO_SINGLE)); +} +#endif +int edit_outs(char *text) { + register int column = 0; + register char ch; +#ifdef SUPPORT_GB + if(current_font_type == TYPE_GB) + text = hc_convert_str(text, HC_BIGtoGB, HC_DO_SINGLE); +#endif + while((ch = *text++) && (++column < SCR_WIDTH)) + outch(ch == 27 ? '*' : ch); + + return 0; +} + +void outs(char *str) { +#ifdef SUPPORT_GB + if(current_font_type == TYPE_BIG5) +#endif + do_outs(str); +#ifdef SUPPORT_GB + else + { + if(!gbinited) gb_init(); + gb_outs(str); + } +#endif +} + + +/* Jaky */ +void Jaky_outs(char *str, int line) { +#ifdef SUPPORT_GB + if(current_font_type == TYPE_GB) + str = hc_convert_str(str, HC_BIGtoGB, HC_DO_SINGLE); +#endif + while(*str && line) { + outc(*str); + if(*str=='\n') + line--; + str++; + } +} + +void outmsg(char *msg) { + move(b_lines, 0); + clrtoeol(); +#ifdef SUPPORT_GB + if(current_font_type == TYPE_GB) + msg = hc_convert_str(msg, HC_BIGtoGB, HC_DO_SINGLE); +#endif + while(*msg) + outc(*msg++); +} + +void prints(char *fmt, ...) { + va_list args; + char buff[1024]; + + va_start(args, fmt); + vsprintf(buff, fmt, args); + va_end(args); + outs(buff); +} + +void mprints(int y, int x, char *str) { + move(y, x); + clrtoeol(); + prints(str); +} + +void scroll() { + scrollcnt++; + if(++roll >= scr_lns) + roll = 0; + move(b_lines, 0); + clrtoeol(); +} + +void rscroll() { + 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() { + if(!standing && strtstandoutlen) { + register screenline_t *slp; + + slp = &big_picture[((cur_ln + roll) % scr_lns)]; + standing = YEA; + slp->sso = slp->eso = cur_col; + slp->mode |= STANDOUT; + } +} + +void standend() { + if(standing && strtstandoutlen) { + register screenline_t *slp; + + slp = &big_picture[((cur_ln + roll) % scr_lns)]; + standing = NA; + slp->eso = MAX(slp->eso, cur_col); + } +} diff --git a/mbbsd/stuff.c b/mbbsd/stuff.c new file mode 100644 index 00000000..9218b7f0 --- /dev/null +++ b/mbbsd/stuff.c @@ -0,0 +1,524 @@ +/* $Id: stuff.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <unistd.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +extern int currmode; +extern char *fn_mandex; +extern char *str_reply; +extern char *str_space; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern userec_t cuser; + +/* ----------------------------------------------------- */ +/* set file path for boards/user home */ +/* ----------------------------------------------------- */ +static char *str_home_file = "home/%c/%s/%s"; +static char *str_board_file = "boards/%s/%s"; + +#define STR_DOTDIR ".DIR" +static char *str_dotdir = STR_DOTDIR; + +void setcalfile(char *buf, char *userid) { + sprintf(buf, "home/%c/%s/calendar", userid[0], userid); +} + +void sethomepath(char *buf, char *userid) { + sprintf(buf, "home/%c/%s", userid[0], userid); +} + +void sethomedir(char *buf, char *userid) { + sprintf(buf, str_home_file, userid[0], userid, str_dotdir); +} + +void sethomeman(char *buf, char *userid) { + sprintf(buf, str_home_file, userid[0], userid, "man"); +} + +void sethomefile(char *buf, char *userid, char *fname) { + sprintf(buf, str_home_file, userid[0], userid, fname); +} + +void setuserfile(char *buf, char *fname) { + sprintf(buf, str_home_file, cuser.userid[0], cuser.userid, fname); +} + +void setapath(char *buf, char *boardname) { + sprintf(buf, "man/boards/%s", boardname); +} + +void setadir(char *buf, char *path) { + sprintf(buf, "%s/%s", path, str_dotdir); +} + +void setbpath(char *buf, char *boardname) { + sprintf(buf, "boards/%s", boardname); +} + +void setbdir(char *buf, char *boardname) { + sprintf(buf, str_board_file, boardname, + currmode & MODE_ETC ? ".ETC" : + (currmode & MODE_DIGEST ? fn_mandex : str_dotdir)); +} + +void setbfile(char *buf, char *boardname, char *fname) { + sprintf(buf, str_board_file, boardname, fname); +} + +void setdirpath(char *buf, char *direct, char *fname) { + strcpy(buf, direct); + direct = strrchr(buf, '/'); + strcpy(direct + 1, fname); +} + +char *subject(char *title) { + if(!strncasecmp(title, str_reply, 3)) { + title += 3; + if(*title == ' ') + title++; + } + return title; +} + +/* ----------------------------------------------------- */ +/* �r���ഫ�ˬd��� */ +/* ----------------------------------------------------- */ +int str_checksum(char *str) { + int n = 1; + if(strlen(str) < 6) + return 0; + while(*str) + n += *(str++) * (n); + return n; +} + +void str_lower(char *t, char *s) { + register unsigned char ch; + + do { + ch = *s++; + *t++ = char_lower(ch); + } while(ch); +} + +int strstr_lower(char *str, char *tag) { + char buf[STRLEN]; + + str_lower(buf, str); + return (int)strstr(buf, tag); +} + +void trim(char *buf) { /* remove trailing space */ + char *p = buf; + + while(*p) + p++; + while(--p >= buf) { + if(*p == ' ') + *p = '\0'; + else + break; + } +} + +/* ----------------------------------------------------- */ +/* �r���ˬd��ơG�^��B�Ʀr�B�ɦW�BE-mail address */ +/* ----------------------------------------------------- */ +int isprint2(char ch) { + return ((ch & 0x80) ? 1 : isprint(ch)); + //return 1; +} + +int not_alpha(char ch) { + return (ch < 'A' || (ch > 'Z' && ch < 'a') || ch > 'z'); +} + +int not_alnum(char ch) { + return (ch < '0' || (ch > '9' && ch < 'A') || + (ch > 'Z' && ch < 'a') || ch > 'z'); +} + +int invalid_pname(char *str) { + char *p1, *p2, *p3; + + p1 = str; + while(*p1) { + if(!(p2 = strchr(p1, '/'))) + p2 = str + strlen(str); + if(p1 + 1 > p2 || p1 + strspn(p1, ".") == p2) + return 1; + for(p3 = p1; p3 < p2; p3++) + if(not_alnum(*p3) && !strchr("@[]-._", *p3)) + return 1; + p1 = p2 + (*p2 ? 1 : 0); + } + return 0; +} + +int valid_ident(char *ident) { + static char *invalid[] = {"unknown@", "root@", "gopher@", "bbs@", + "@bbs", "guest@", "@ppp", "@slip", NULL}; + char buf[128]; + int i; + + str_lower(buf, ident); + for(i = 0; invalid[i]; i++) + if(strstr(buf, invalid[i])) + return 0; + return 1; +} + +int is_uBM(char *list, 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(char *list) { + if(is_uBM(list,cuser.userid)) { + cuser.userlevel |= PERM_BM; /* Ptt �۰ʥ[�WBM���v�Q */ + return 1; + } + return 0; +} + +int userid_is_BM(char *userid, char *list) { + register int ch, len; + + 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; +} + +/* ----------------------------------------------------- */ +/* �ɮ��ˬd��ơG�ɮסB�ؿ��B�ݩ� */ +/* ----------------------------------------------------- */ +off_t dashs(char *fname) { + struct stat st; + + if(!stat(fname, &st)) + return st.st_size; + else + return -1; +} + +long dasht(char *fname) { + struct stat st; + + if(!stat(fname, &st)) + return st.st_mtime; + else + return -1; +} + +int dashl(char *fname) { + struct stat st; + + return (lstat(fname, &st) == 0 && S_ISLNK(st.st_mode)); +} + +int dashf(char *fname) { + struct stat st; + + return (stat(fname, &st) == 0 && S_ISREG(st.st_mode)); +} + +int dashd(char *fname) { + struct stat st; + + return (stat(fname, &st) == 0 && S_ISDIR(st.st_mode)); +} + +int belong(char *filelist, char *key) { + FILE *fp; + int rc = 0; + + if((fp = fopen(filelist, "r"))) { + char buf[STRLEN], *ptr; + + while(fgets(buf, STRLEN, fp)) { + if((ptr = strtok(buf, str_space)) && !strcasecmp(ptr, key)) { + rc = 1; + break; + } + } + fclose(fp); + } + return rc; +} + +char *Cdate(time_t *clock) { + static char foo[32]; + struct tm *mytm = localtime(clock); + + strftime(foo, 32, "%m/%d/%Y %T %a", mytm); + return foo; +} + +char *Cdatelite(time_t *clock) { + static char foo[32]; + struct tm *mytm = localtime(clock); + + strftime(foo, 32, "%m/%d/%Y %T", mytm); + return foo; +} + +char *Cdatedate(time_t *clock){ + static char foo[32]; + struct tm *mytm = localtime(clock); + + strftime(foo, 32, "%m/%d/%Y", mytm); + return foo; +} + +static void capture_screen() { + char fname[200]; + FILE* fp; + extern screenline_t *big_picture; + extern unsigned char scr_lns; + int i; + + getdata(b_lines - 2, 0, "��o�ӵe�����J��Ȧs�ɡH[y/N] ", + fname, 4, LCECHO); + if(fname[0] != 'y' ) return; + + setuserfile(fname, ask_tmpbuf(b_lines - 1)); + if((fp = fopen(fname, "w"))) { + for(i = 0; i < scr_lns; i++) + fprintf(fp, "%.*s\n", big_picture[i].len, big_picture[i].data); + fclose(fp); + } +} + +void pressanykey() { + int ch; + + outmsg("\033[37;45;1m " + "�� �Ы� \033[33m(Space/Return)\033[37m �~�� ��" + " \033[33m(^T)\033[37m �s�Ȧs�� \033[m"); + do { + ch = igetkey(); + + if(ch == Ctrl('T')) { + capture_screen(); + break; + } + } while((ch != ' ') && (ch != KEY_LEFT) && (ch != '\r') && (ch != '\n')); + move(b_lines, 0); + clrtoeol(); + refresh(); +} + +int vmsg (const char *fmt, ...) +{ + va_list ap; + char msg[80] = {0}; + int ch; + + va_start (ap, fmt); + vsprintf (msg, fmt, ap); + va_end (ap); + + move (b_lines, 0); + clrtoeol (); + + if (*msg) + prints ("\033[1;36;44m �� %-55.54s \033[33;46m \033[200m\033[1431m\033[506m[�Ы����N���~��]\033[201m \033[m", msg); + else + outs ("\033[46;1m \033[37m" + "\033[200m\033[1431m\033[506m�� �Ы� \033[33m(Space/Return)\033[37m �~�� ��\033[201m" + " \033[m"); + + do { + ch = igetkey(); + + if(ch == Ctrl('T')) { + capture_screen(); + break; + } + } while((ch != ' ') && (ch != KEY_LEFT) && (ch != '\r') && (ch != '\n')); + + + move (b_lines, 0); + clrtoeol (); + refresh (); + return ch; +} + +void bell() { + char c; + + c = Ctrl('G'); + write(1, &c, 1); +} + +int search_num(int ch, int max) { + int clen = 1; + int x, y; + extern unsigned char scr_cols; + char genbuf[10]; + + outmsg("\033[7m ���ܲĴX���G\033[m"); + outc(ch); + genbuf[0] = ch; + getyx(&y, &x); + x--; + while((ch = igetch()) != '\r') { + if(ch == 'q' || ch == 'e') + return -1; + if(ch == '\n') + break; + if(ch == '\177' || ch == Ctrl('H')) { + if(clen == 0) { + bell(); + continue; + } + clen--; + move(y, x + clen); + outc(' '); + move(y, x + clen); + continue; + } + if(!isdigit(ch)) { + bell(); + continue; + } + if(x + clen >= scr_cols || clen >= 6) { + bell(); + continue; + } + genbuf[clen++] = ch; + outc(ch); + } + genbuf[clen] = '\0'; + move(b_lines, 0); + clrtoeol(); + if(genbuf[0] == '\0') + return -1; + clen = atoi(genbuf); + if(clen == 0) + return 0; + if(clen > max) + return max; + return clen - 1; +} + +void stand_title(char *title) { + clear(); + prints("\033[1;37;46m�i %s �j\033[m\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 = egetch(); + move(row, column); + outs(STR_UNCUR); + return ch; +} + +void printdash(char *mesg) { + int head = 0, tail; + + if(mesg) + head = (strlen(mesg) + 1) >> 1; + + tail = head; + + while(head++ < 38) + outch('-'); + + if(tail) { + outch(' '); + outs(mesg); + outch(' '); + } + + while(tail++ < 38) + outch('-'); + outch('\n'); +} + +int log_file(char *filename,char *buf) { + FILE *fp; + + if((fp = fopen(filename, "a" )) != NULL ) { + fputs( buf, fp ); + if(!strchr(buf,'\n')) + fputc('\n',fp); + fclose( fp ); + return 0; + } + else + return -1; +} + +void show_help(char *helptext[]) { + char *str; + int i; + + clear(); + for(i = 0; (str = helptext[i]); i++) { + if(*str == '\0') + prints("\033[1m�i %s �j\033[0m\n", str + 1); + else if(*str == '\01') + prints("\n\033[36m�i %s �j\033[m\n", str + 1); + else + prints(" %s\n", str); + } + pressanykey(); +} diff --git a/mbbsd/syspost.c b/mbbsd/syspost.c new file mode 100644 index 00000000..b7aefe10 --- /dev/null +++ b/mbbsd/syspost.c @@ -0,0 +1,102 @@ +/* $Id: syspost.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "perm.h" +#include "common.h" +#include "proto.h" + +extern char *str_permid[]; +extern userec_t cuser; + +void post_change_perm(int oldperm, int newperm, char *sysopid, char *userid) { + FILE *fp; + fileheader_t fhdr; + time_t now = time(0); + char genbuf[200], reason[30]; + int i, flag=0; + + strcpy(genbuf, "boards/Security"); + stampfile(genbuf, &fhdr); + if(!(fp = fopen(genbuf,"w"))) + return; + + fprintf(fp, "�@��: [�t�Φw����] �ݪO: Security\n" + "���D: [���w���i] �����ק��v�����i\n" + "�ɶ�: %s\n", ctime(&now)); + for(i = 5; i < NUMPERMS; i++) { + if(((oldperm >> i) & 1) != ((newperm >> i) & 1)) { + fprintf (fp, " ����\033[1;32m%s%s%s%s\033[m���v��\n", + sysopid, + (((oldperm >> i) & 1) ? "\033[1;33m����":"\033[1;33m�}��"), + userid, str_permid[i]); + flag++; + } + } + + if(flag) { + clrtobot(); + clear(); + while(!getdata_str(5, 0, "�п�J�z�ѥH�ܭt�d�G", + reason, 60, DOECHO, "�ݪ����D:")); + fprintf(fp, "\n \033[1;37m����%s�ק��v���z�ѬO�G%s\033[m", + cuser.userid, reason); + fclose(fp); + + sprintf(fhdr.title, "[���w���i] ����%s�ק�%s�v�����i", + cuser.userid, userid); + strcpy(fhdr.owner, "[�t�Φw����]"); + append_record("boards/Security/.DIR", &fhdr, sizeof(fhdr)); + } +} + +void post_violatelaw(char* crime, char* police, char* reason, char* result){ + char genbuf[200]; + fileheader_t fhdr; + time_t now; + FILE *fp; + strcpy(genbuf, "boards/Security"); + stampfile(genbuf, &fhdr); + if(!(fp = fopen(genbuf,"w"))) + return; + now = time(NULL); + fprintf(fp, "�@��: [Ptt�k�|] �ݪO: Security\n" + "���D: [���i] %-20s �H�k�P�M���i\n" + "�ɶ�: %s\n" + "\033[1;32m%s\033[m�P�M�G\n \033[1;32m%s\033[m" + "�]\033[1;35m%s\033[m�欰�A\n�H�ϥ������W�A�B�H\033[1;35m%s\033[m�A�S�����i", + crime, ctime(&now), police, crime, reason, result); + fclose(fp); + sprintf(fhdr.title, "[���i] %-20s �H�k�P�M���i", crime); + strcpy(fhdr.owner, "[Ptt�k�|]"); + append_record("boards/Security/.DIR", &fhdr, sizeof(fhdr)); + + strcpy(genbuf, "boards/ViolateLaw"); + stampfile(genbuf, &fhdr); + if(!(fp = fopen(genbuf,"w"))) + return; + now = time(NULL); + fprintf(fp, "�@��: [Ptt�k�|] �ݪO: ViolateLaw\n" + "���D: [���i] %-20s �H�k�P�M���i\n" + "�ɶ�: %s\n" + "\033[1;32m%s\033[m�P�M�G\n \033[1;32m%s\033[m" + "�]\033[1;35m%s\033[m�欰�A\n�H�ϥ������W�A�B�H\033[1;35m%s\033[m�A�S�����i", + crime, ctime(&now), police, crime, reason, result); + fclose(fp); + sprintf(fhdr.title, "[���i] %-20s �H�k�P�M���i", crime); + strcpy(fhdr.owner, "[Ptt�k�|]"); + + append_record("boards/ViolateLaw/.DIR", &fhdr, sizeof(fhdr)); + +} + +void post_newboard(char* bgroup, char* bname, char* bms){ + char genbuf[256], title[128]; + sprintf(title, "[�s������] %s", bname); + sprintf(genbuf, "%s �}�F�@�ӷs�� %s : %s\n\n�s�����D�� %s\n\n����*^_^*\n", + cuser.userid, bname, bgroup, bms); + post_msg("Record", title, genbuf, "[�t��]"); +} diff --git a/mbbsd/talk.c b/mbbsd/talk.c new file mode 100644 index 00000000..3012b2d2 --- /dev/null +++ b/mbbsd/talk.c @@ -0,0 +1,2663 @@ +/* $Id: talk.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <syslog.h> +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> +#include <netdb.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +#define QCAST int (*)(const void *, const void *) + +extern userinfo_t *currutmp; +extern char *ModeTypeTable[MAX_MODES]; +extern char *fn_overrides; +extern int usernum; +extern char *msg_sure_ny; +extern char *msg_cancel; +extern unsigned int currstat; +extern char *fn_writelog; +extern FILE *fp_writelog; +extern pid_t currpid; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern int t_lines, t_columns; /* Screen size / width */ +extern char *fn_talklog; +extern char currauthor[IDLEN + 2]; +extern char *msg_usr_left; +extern char *msg_uid; +extern char *BBSName; +extern int p_lines; /* a Page of Screen line numbers: tlines-4 */ +extern char fromhost[]; +extern char *err_uid; +extern int talkrequest; +extern char *msg_shortulist; +extern char *msg_nobody; +extern boardheader_t *bcache; +extern int curr_idle_timeout; +extern userec_t cuser; +extern userec_t xuser; + + +static char *IdleTypeTable[] = { + "���b��b��", "���H�ӹq", "�V����", "�����P��", "�������A", "�ڦb���" +}; +static char *sig_des[] = { + "����", "���", "", "�U��", "�H��", "�t��" +}; + +#define MAX_SHOW_MODE 3 +#define M_INT 15 /* monitor mode update interval */ +#define P_INT 20 /* interval to check for page req. in + * talk/chat */ +#define BOARDFRI 1 + +typedef struct talkwin_t { + int curcol, curln; + int sline, eline; +} talkwin_t; + +typedef struct pickup_t { + userinfo_t *ui; + time_t idle; + int friend; +} pickup_t; + +extern int bind( /* int,struct sockaddr *, int */ ); +extern char *getuserid(); +extern struct utmpfile_t *utmpshm; +extern int watermode; +extern water_t water[6], *swater[5], *water_which; +extern char *friend_file[8], water_usies; + +/* �O�� friend �� user number */ +//#define PICKUP_WAYS 7 //�����k�h�u�� +#define PICKUP_WAYS 6 + +static int pickup_way = 0; +static char *fcolor[11] = { + "", "\033[36m", "\033[32m", "\033[1;32m", + "\033[33m", "\033[1;33m", "\033[1;37m", "\033[1;37m", + "\033[31m", "\033[1;35m", "\033[1;36m" +}; +static char save_page_requestor[40]; +static char page_requestor[40]; +static char description[30]; +static FILE *flog; + + +char *modestring(userinfo_t * uentp, int simple) { + static char modestr[40]; + static char *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 (!(HAS_PERM(PERM_SYSOP) || HAS_PERM(PERM_SEECLOAK)) && + ( + (uentp->invisible || (fri_stat & HRM)) && + !((fri_stat & HFM) && (fri_stat & HRM)) + ) + ) + return notonline; + else if (mode == EDITING) + { + sprintf(modestr, "E:%s", + ModeTypeTable[uentp->destuid < EDITING ? uentp->destuid : + EDITING]); + word = modestr; + } + else if (!mode && *uentp->chatid == 1) + { + if (!simple) + sprintf(modestr, "�^�� %s", getuserid(uentp->destuid)); + else + sprintf(modestr, "�^���I�s"); + } + else if (!mode && *uentp->chatid == 2) + if (uentp->msgcount < 10) + { + char *cnum[10] = + {"", "�@", "��", "�T", "�|", "��", "��", "�C", + "�K", "�E"}; + sprintf(modestr, "��%s�����y", cnum[uentp->msgcount]); + } + else + sprintf(modestr, "����F @_@"); + else if (!mode && *uentp->chatid == 3) + sprintf(modestr, "���y�dzƤ�"); + 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) + sprintf(modestr, "%s (%s)", word, uentp->chatid); + else if (mode == TALK) + { + if (!isvisible_uid(uentp->destuid))/* Leeym ���(����)���� */ + sprintf(modestr, "%s", "��� �Ů�");/* Leeym �j�a�ۤv�o���a�I */ + else + sprintf(modestr, "%s %s", word, getuserid(uentp->destuid)); + } + else if (mode == M_FIVE) + { + if (!isvisible_uid(uentp->destuid)) + sprintf(modestr, "%s", "���l�� �Ů�"); + else + sprintf(modestr, "%s %s", word, getuserid(uentp->destuid)); + } + else if (mode == CHC) + { + if (isvisible_uid(uentp->destuid)) + sprintf(modestr, "%s", "�U�H��"); + else + sprintf(modestr, "�U�H�� %s", getuserid(uentp->destuid)); + } + else if (mode != PAGE && mode != TQUERY) + return word; + else + sprintf(modestr, "%s %s", word, getuserid(uentp->destuid)); + + return (modestr); +} + +int set_friend_bit(userinfo_t * me, userinfo_t * ui) { + int unum, *myfriends, hit=0, n; + +/* �P�_���O�_���ڪ��B�� ? */ + unum = ui->uid; + myfriends = me->friend; + while ((n = *myfriends++)) + { + if (unum == n) + { + hit = IFH; + break; + } + } + +/* �P�_�ڬO�_����誺�B�� ? */ + myfriends = ui->friend; + while ((unum = *myfriends++)) + { + if (unum == me->uid) + { + hit |= HFM; + break; + } + } + +/* �P�_���O�_���ڪ����H ? */ + + unum = ui->uid; + myfriends = me->reject; + while ((n = *myfriends++)) + { + if (unum == n) + { + hit |= IRH; + break; + } + } + +/* �P�_�ڬO�_����誺���H ? */ + myfriends = ui->reject; + while ((unum = *myfriends++)) + { + if (unum == me->uid) + { + hit |= HRM; + break; + } + } + return hit; +} +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; +} + +int login_friend_online(){ + userinfo_t *uentp; + int i, stat, stat1; + int offset=(int) (currutmp - &utmpshm->uinfo[0]); + for (i=0;i<utmpshm->number && currutmp->friendtotal<MAX_FRIEND; i++) + { + uentp = (utmpshm->sorted[utmpshm->currsorted][0][i]); + if(uentp && uentp->uid && (stat=set_friend_bit(currutmp,uentp))) + { + stat1=reverse_friend_stat(stat); + stat <<= 24; + stat |= (int) (uentp - &utmpshm->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 0; +} + +int logout_friend_online(){ + int i, j, k; + int offset=(int) (currutmp - &utmpshm->uinfo[0]); + userinfo_t *ui; + while(currutmp->friendtotal) + { + i = currutmp->friendtotal-1; + j = (currutmp->friend_online[i] & 0xFFFFFF); + currutmp->friend_online[i]=0; + ui = &utmpshm->uinfo[j]; + if(ui->pid && ui!=currutmp) + { + for(k=0; k<ui->friendtotal && + (int)(ui->friend_online[k] & 0xFFFFFF) !=offset; k++); + if(k<ui->friendtotal) + { + ui->friendtotal--; + ui->friend_online[k]=ui->friend_online[ui->friendtotal]; + ui->friend_online[ui->friendtotal]=0; + } + } + currutmp->friendtotal--; + currutmp->friend_online[currutmp->friendtotal]=0; + } + return 0; +} + + +int friend_stat(userinfo_t *me, 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++) + { + j = (me->friend_online[i] & 0xFFFFFF); + if(ui == &utmpshm->uinfo[j]) + { + hit |= me->friend_online[i] >>24; + break; + } + } + if (PERM_HIDE(ui)) + return hit & ST_FRIEND; + return hit; +} + +int isvisible_stat(userinfo_t * me, userinfo_t * uentp, int fri_stat) { + if (uentp->userid[0] == 0) + 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) ? 0 : 1; +} + +int isvisible(userinfo_t * me, userinfo_t * uentp) { + return isvisible_stat(currutmp, uentp, friend_stat(me, uentp)); +} + +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') + { + sprintf(genbuf, "%s (%s)", uentp->userid, uentp->username); + 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(); +} + +static void chicken_query(char *userid) { + char buf[100]; + + if (getuser(userid)) + { + if (xuser.mychicken.name[0]) + { + time_diff(&(xuser.mychicken)); + if (!isdeadth(&(xuser.mychicken))) + { + show_chicken_data(&(xuser.mychicken), NULL); + sprintf(buf, "\n\n�H�W�O %s ���d�����..", userid); + outs(buf); + } + } + else + { + move(1, 0); + clrtobot(); + sprintf(buf, "\n\n%s �èS���i�d��..", userid); + outs(buf); + } + pressanykey(); + } +} + +int my_query(char *uident) { + userec_t muser; + int tuid, i, fri_stat=0; + unsigned long int j; + userinfo_t *uentp; + static const char *money[10] = + {"�ťx���v", "���h", "�M�H", "���q", "�p�d", + "�p�I", "���I", "�j�I��", "�I�i�İ�", "�\\��"}, + *sex[8] = + {MSG_BIG_BOY, MSG_BIG_GIRL, + MSG_LITTLE_BOY, MSG_LITTLE_GIRL, + MSG_MAN, MSG_WOMAN, MSG_PLANT, MSG_MIME}; + + + if ((tuid = getuser(uident))) + { + memcpy(&muser, &xuser, sizeof(muser)); + move(1, 0); + clrtobot(); + move(1, 0); + setutmpmode(TQUERY); + currutmp->destuid = tuid; + + j = muser.money; + for (i = 0; i < 10 && j > 10; i++) + j /= 10; + prints("�m�עҼʺ١n%s(%s)%*s�m�g�٪��p�n%s\n", + muser.userid, + muser.username, + 26 - strlen(muser.userid) - strlen(muser.username), "", + money[i]); + prints("�m�W�����ơn%d��", muser.numlogins); + move(2, 40); + prints("�m�峹�g�ơn%d�g\n", muser.numposts); + + if((uentp = (userinfo_t *) search_ulist(tuid))) + fri_stat=friend_stat(currutmp, uentp); + prints("\033[1;33m�m�ثe�ʺA�n%-28.28s\033[m", + (uentp && isvisible_stat(currutmp, uentp, fri_stat)) ? + modestring(uentp, 0) : "���b���W"); + + outs(((uentp && uentp->mailalert) || 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 : "(����)")); + if ((uentp && fri_stat&HFM) || HAS_PERM(PERM_SYSOP)) + prints("�m �� �O �n%-28.28s�m�p���]���n%ld �Ȩ�\n", + sex[muser.sex % 8], + muser.money); + prints("�m���l�Ѿ��Z�n%3d �� %3d �� %3d �M " + "�m�H�Ѿ��Z�n%3d �� %3d �� %3d �M", + muser.five_win, muser.five_lose, muser.five_tie, + muser.chc_win, muser.chc_lose, muser.chc_tie); + showplans(uident); + pressanykey(); + return FULLUPDATE; + } + return DONOTHING; +} + +static char t_last_write[200] = ""; + +void water_scr(water_t **currwater, int which, char type) +{ + if( type == 1 ){ + int i; + int colors[] = {33, 37, 33, 37, 33}; + move(8 + which, 28);prints(" "); + move(8 + which, 28); + prints("\033[1;37;45m %-14s \033[0m", currwater[which]->userid); + for( i = 0 ; i < 5 ; ++i ){ + move(16 + i, 4); + prints(" "); + move(16 + i, 4); + if( currwater[which]->msg[ (currwater[which]->top-i+4) % 5 ].last_call_in[0] != 0 ) + prints("\033[0m \033[1;%d;44m��%-64s\033[0m \n", + colors[i], + currwater[which]->msg[ (currwater[which]->top-i+4) % 5 ].last_call_in); + else + prints("\033[0m�@\n"); + } + move(0, 0);prints(" "); + move(0, 0); + prints("\033[0m���� %s:", currwater[which]->userid); + clrtoeol(); + move(0, strlen(currwater[which]->userid) + 6); + } + else{ + move(8 + which, 28); + prints("123456789012345678901234567890"); + // refresh(); + move(8 + which, 28); + prints("\033[1;37;44m %-13s�@\033[0m", currwater[which]->userid); + // refresh(); + } +} + +void my_write2(void) +{ + int i, ch, currstat0, currwater_usies; + char genbuf[256], msg[80], done = 0, c0, which; + water_t *tw, *currwater[5]; + unsigned char mode0; + + watermode = 0; + currstat0 = currstat; + c0 = currutmp->chatid[0]; + mode0 = currutmp->mode; + currutmp->mode = 0; + currutmp->chatid[0] = 3; + currstat = XMODE; + + // init screen + memcpy(currwater, swater, sizeof(water_t*) * 5); + currwater_usies = water_usies; + move(7, 28); + prints("\033[1;33;46m �� ���y������H ��\033[0m"); + for( i = 0 ; i < 5 ; ++i ) + if( currwater[i] == NULL || currwater[i]->pid == 0 ) + break; + else + water_scr(currwater, i, 0); + move(15, 4); + prints("\033[0m \033[1;35m��\033[1;36m�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\033[1;35m��\033[0m "); + move(22, 4); + prints(" \033[1;35m��\033[1;36m�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\033[1;35m��\033[0m "); + move(21, 4);prints(" "); + move(21, 4); + prints("\033[0m \033[1;37;46m%-66s\033[0m \n", t_last_write); + water_scr(currwater, 0, 1); + refresh(); + + which = 0; + do{ + switch( (ch = igetkey()) ){ + case Ctrl('T'): + case KEY_UP: + if( currwater_usies != 1 ){ + water_scr(currwater, which, 0); + which = (which - 1 + currwater_usies) % currwater_usies; + water_scr(currwater, which, 1); + refresh(); + } + break; + + case KEY_DOWN: + case Ctrl('R'): + if( currwater_usies != 1 ){ + water_scr(currwater, which, 0); + which = (which + 1 + currwater_usies) % currwater_usies; + water_scr(currwater, which, 1); + refresh(); + } + break; + + case KEY_LEFT: + done = 1; + break; + + default: + done = 1; + watermode = 1; + tw = currwater[(int)which]; + + if( ch != '\r' && ch != '\n' ){ + msg[0] = ch, msg[1] = 0; + } + else + msg[0] = 0; + move(0, 0);prints("\033[m"); clrtoeol(); + refresh(); + sprintf(genbuf, "���� %s:", tw->userid); + if( !oldgetdata(0, 0, genbuf, msg, + 80-strlen(tw->userid)-6, DOECHO) ) + break; + + my_write(tw->pid, msg, tw->userid, 4); + break; + } + } while( !done ); + + watermode = -1; + currstat = currstat0; + currutmp->chatid[0] = c0; + currutmp->mode = mode0; +} + +/* + �Q�I�s���ɾ�: + 1. ��s�դ��y flag = 1 (pre-edit) + 2. �^���y flag = 0 + 3. �W��aloha flag = 2 (pre-edit) + 4. �s�� flag = 3 if SYSOP, otherwise flag = 1 (pre-edit) + 5. ����y flag = 0 + 6. my_write2 flag = 4 (pre-edit) but confirm +*/ +int my_write(pid_t pid, char *prompt, char *id, int flag) { + int len, currstat0 = currstat, fri_stat; + char msg[80], destid[IDLEN + 1]; + char genbuf[200], buf[200], c0 = currutmp->chatid[0]; + unsigned char mode0 = currutmp->mode; + time_t now; + struct tm *ptime; + userinfo_t *uin; + uin = (userinfo_t *)search_ulist_pid(pid); + strcpy(destid, id); + + if(!uin && !(flag == 0 && water_which->count> 0)) { + outmsg("\033[1;33;41m�V�|! ���w���]�F(���b���W)! \033[37m~>_<~\033[m"); + clrtoeol(); + refresh(); + watermode = -1; + return 0; + } + currutmp->mode = 0; + currutmp->chatid[0] = 3; + currstat = XMODE; + + time(&now); + ptime = localtime(&now); + + if(flag == 0) { + /* �@����y */ + watermode = 0; + if(!(len = getdata(0, 0, prompt, msg, 56, DOECHO))) { + outmsg("\033[1;33;42m��F! ��A�@��...\033[m"); + clrtoeol(); + refresh(); + 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); + strcpy(destid, water_which->msg[i].userid); + } + } else { + /* pre-edit �����y */ + strcpy(msg, prompt); + len = strlen(msg); + } + + watermode = -1; + strip_ansi(msg, msg, 0); + if(uin && *uin->userid && (flag == 0 || flag == 4)) { + sprintf(buf, "�ᵹ %s : %s [Y/n]?", uin->userid, msg); + getdata(0, 0, buf, genbuf, 3, LCECHO); + if(genbuf[0] == 'n') { + outmsg("\033[1;33;42m��F! ��A�@��...\033[m"); + clrtoeol(); + refresh(); + currutmp->chatid[0] = c0; + currutmp->mode = mode0; + currstat = currstat0; + watermode = -1; + return 0; + } + } + + if(!uin || !*uin->userid || strcasecmp(destid, uin->userid)) { + outmsg("\033[1;33;41m�V�|! ���w���]�F(���b���W)! \033[37m~>_<~\033[m"); + clrtoeol(); + refresh(); + currutmp->chatid[0] = c0; + currutmp->mode = mode0; + currstat = currstat0; + return 0; + } + + fri_stat=friend_stat(currutmp, uin); + time(&now); + if(flag != 2) { /* 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", + uin->userid, msg, Cdatelite(&now)); + snprintf(t_last_write, 66, "To %s: %s", uin->userid, msg); + } + } + + if(flag == 3 && uin->msgcount) { + /* ���� */ + uin->destuip = currutmp - &utmpshm->uinfo[0]; + uin->sig = 2; + if(uin->pid > 0) kill(uin->pid, SIGUSR1); + } else if(flag != 2 && + !HAS_PERM(PERM_SYSOP) && + (uin->pager == 3 || + uin->pager == 2 || + (uin->pager == 4 && + !(fri_stat & HFM)))) + outmsg("\033[1;33;41m�V�|! ��訾���F! \033[37m~>_<~\033[m"); + else { + if(uin->msgcount < MAX_MSGS) { + unsigned char pager0 = uin->pager; + + uin->pager = 2; + uin->msgs[uin->msgcount].pid = currpid; + strcpy(uin->msgs[uin->msgcount].userid, cuser.userid); + strcpy(uin->msgs[uin->msgcount++].last_call_in, msg); + uin->pager = pager0; + } else if (flag != 2) + outmsg("\033[1;33;41m�V�|! ��褣��F! (����Ӧh���y) \033[37m@_@\033[m"); + + if(uin->msgcount == 1 && (uin->pid <= 0 || kill(uin->pid, SIGUSR2) == -1) && flag != 2) + outmsg("\033[1;33;41m�V�|! �S����! \033[37m~>_<~\033[m"); + else if(uin->msgcount == 1 && flag != 2) + outmsg("\033[1;33;44m���y�{�L�h�F! \033[37m*^o^*\033[m"); + else if(uin->msgcount > 1 && uin->msgcount < MAX_MSGS && flag != 2) + outmsg("\033[1;33;44m�A�ɤW�@��! \033[37m*^o^*\033[m"); + } + + clrtoeol(); + refresh(); + + currutmp->chatid[0] = c0; + currutmp->mode = mode0; + currstat = currstat0; + return 1; +} +void t_display_new() { + static int t_display_new_flag=0; + int i, off=2; + if (t_display_new_flag) + return; + else + t_display_new_flag = 1; + + 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-E Ctrl-W ]������w�w�w�w"); + if( WATERMODE(WATER_NEW) ){ + move(2, 0); + clrtoeol(); + for (i = 0; i<6 ; i++){ + if(i>0) + prints("%s%-13.13s\033[m", + swater[i-1]==water_which?"\033[1;33;47m ": + " ", + swater[i-1] ? swater[i-1]->userid:""); + else + prints("%s ���� \033[m", + water_which==&water[0]?"\033[1;33;45m ": + " "); + } + } + + for (i = 0; i < water_which->count; i++){ + int a = (water_which->top - i - 1 + MAX_REVIEW) % MAX_REVIEW, + len = 75-strlen(water_which->msg[a].last_call_in) + -strlen(water_which->msg[a].userid); + if(len<0) len=0; + + move(i + (WATERMODE(WATER_ORIG)?2:3), 0); + clrtoeol(); + if (watermode - 1 != i) + prints("\033[1;33;46m %s \033[37;45m %s \033[m%*s", + water_which->msg[a].userid, + water_which->msg[a].last_call_in, len, + ""); + else + prints("\033[1;44m>\033[1;33;47m%s " + "\033[37;45m %s \033[m%*s", + water_which->msg[a].userid, + water_which->msg[a].last_call_in, + len,""); + } + + if (t_last_write[0]){ + move(i + off, 0); + clrtoeol(); + prints(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; +} +#if 0 +void t_display_new() { + int i, which=water_which; + char buf[200]; + + if (t_display_new_flag) + return; + else + t_display_new_flag = 1; + + if (oldmsg_count && watermode > 0) + { + move(1, 0); + outs( + "�w�w�w�w�w�w�w���w�y�w�^�w�U�w�w�w�w�w�w�w�w�w" + "��[Ctrl-R Ctrl-T]������w�w�w�w�w"); + move(2, 0); + prints(" |"); + for (i = 0; i<5 && water[i].pid != 0; i++) + prints(" %s%13.13s \033[m|",which==i?"\033[1;33m":"", + water[i].userid); + + for( i = 0 ; i < 5 && + water[which].msg[ (water[which].msgtop-i+4) % 5 ][0] != 0; ++i ){ + move(3 + i, 0); + if (watermode - 1 != i) + sprintf(buf, "\033[1;33;46m %s \033[37;45m %s \033[m", + water[which].userid, + water[which].msg[ (water[which].msgtop-i+4) % 5 ]); + else + sprintf(buf, "\033[1;44m>\033[1;33;47m%s \033[37;45m %s \033[m", + water[which].userid, + water[which].msg[ (water[which].msgtop-i+4) % 5 ]); + } + /* + for (i = 0; i < oldmsg_count; i++) + { + int a = (water[water_which].top - i - 1 + MAX_REVIEW) % MAX_REVIEW; + + move(i + 3, 0); + clrtoeol(); + if (watermode - 1 != i) + sprintf(buf, "\033[1;33;46m %s \033[37;45m %s \033[m", + oldmsg[a].userid, oldmsg[a].last_call_in); + else + sprintf(buf, "\033[1;44m>\033[1;33;47m%s " + "\033[37;45m %s \033[m", + oldmsg[a].userid, oldmsg[a].last_call_in); + outs(buf); + } +*/ + if (t_last_write[0]) + { + move(i + 3, 0); + clrtoeol(); + outs(t_last_write); + i++; + } + move(i + 3, 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�w"); + } + t_display_new_flag = 0; +} +#endif + +int t_display() { + char genbuf[200], ans[4]; + if(fp_writelog) + { fclose(fp_writelog); fp_writelog=NULL;} + setuserfile(genbuf, fn_writelog); + if (more(genbuf, YEA) != -1) + { + getdata(b_lines - 1, 0, "�M��(C) ���ܳƧѿ�(M) �O�d(R) (C/M/R)?[R]", + ans, 3, LCECHO); + if (*ans == 'm') + { + fileheader_t mymail; + char title[128], buf[80]; + + sethomepath(buf, cuser.userid); + stampfile(buf, &mymail); + + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, "[��.��.��]"); + strcpy(mymail.title, "���u\033[37;41m�O��\033[m"); + 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 + region_scroll_up(twin->sline, twin->eline); + move(twin->curln, twin->curcol); +} + +static void do_talk_char(talkwin_t * twin, int ch) { + extern screenline_t *big_picture; + screenline_t *line; + int i; + char ch0, buf[81]; + + if (isprint2(ch)) + { + ch0 = big_picture[twin->curln].data[twin->curcol]; + if (big_picture[twin->curln].len < 79) + move(twin->curln, twin->curcol); + else + do_talk_nextline(twin); + outc(ch); + ++(twin->curcol); + line = big_picture + twin->curln; + if (twin->curcol < line->len) + { /* insert */ + ++(line->len); + memcpy(buf, line->data + twin->curcol, 80); + save_cursor(); + do_move(twin->curcol, twin->curln); + ochar(line->data[twin->curcol] = ch0); + for (i = twin->curcol + 1; i < line->len; i++) + ochar(line->data[i] = buf[i - twin->curcol - 1]); + restore_cursor(); + } + line->data[line->len] = 0; + return; + } + + switch (ch) + { + case Ctrl('H'): + case '\177': + if (twin->curcol == 0) + return; + line = big_picture + twin->curln; + --(twin->curcol); + if (twin->curcol < line->len) + { + --(line->len); + save_cursor(); + do_move(twin->curcol, twin->curln); + for (i = twin->curcol; i < line->len; i++) + ochar(line->data[i] = line->data[i + 1]); + line->data[i] = 0; + ochar(' '); + restore_cursor(); + } + move(twin->curln, twin->curcol); + return; + case Ctrl('D'): + line = big_picture + twin->curln; + if (twin->curcol < line->len) + { + --(line->len); + save_cursor(); + do_move(twin->curcol, twin->curln); + for (i = twin->curcol; i < line->len; i++) + ochar(line->data[i] = line->data[i + 1]); + line->data[i] = 0; + ochar(' '); + restore_cursor(); + } + return; + case Ctrl('G'): + bell(); + return; + case Ctrl('B'): + if (twin->curcol > 0) + { + --(twin->curcol); + move(twin->curln, twin->curcol); + } + return; + case Ctrl('F'): + if (twin->curcol < 79) + { + ++(twin->curcol); + move(twin->curln, twin->curcol); + } + return; + case KEY_TAB: + twin->curcol += 8; + if (twin->curcol > 80) + twin->curcol = 80; + move(twin->curln, twin->curcol); + return; + case Ctrl('A'): + twin->curcol = 0; + move(twin->curln, twin->curcol); + return; + case Ctrl('K'): + clrtoeol(); + return; + case Ctrl('Y'): + twin->curcol = 0; + move(twin->curln, twin->curcol); + clrtoeol(); + return; + case Ctrl('E'): + twin->curcol = big_picture[twin->curln].len; + move(twin->curln, twin->curcol); + return; + case Ctrl('M'): + case Ctrl('J'): + line = big_picture + twin->curln; + strncpy(buf, line->data, line->len); + buf[line->len] = 0; + do_talk_nextline(twin); + break; + case Ctrl('P'): + line = big_picture + twin->curln; + strncpy(buf, line->data, line->len); + buf[line->len] = 0; + if (twin->curln > twin->sline) + { + --(twin->curln); + move(twin->curln, twin->curcol); + } + break; + case Ctrl('N'): + line = big_picture + twin->curln; + strncpy(buf, line->data, line->len); + buf[line->len] = 0; + if (twin->curln < twin->eline) + { + ++(twin->curln); + move(twin->curln, twin->curcol); + } + break; + } + trim(buf); + if (*buf) + fprintf(flog, "%s%s: %s%s\n", + (twin->eline == b_lines - 1) ? "\033[1;35m" : "", + (twin->eline == b_lines - 1) ? + getuserid(currutmp->destuid) : cuser.userid, buf, + (ch == Ctrl('P')) ? "\033[37;45m(Up)\033[m" : "\033[m"); +} + +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; + struct tm *ptime; + time_t now; + char genbuf[200], fpath[100]; + + time(&now); + ptime = localtime(&now); + + sethomepath(fpath, cuser.userid); + strcpy(fpath, tempnam(fpath, "talk_")); + flog = fopen(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); + sprintf(genbuf, "%s�i%s", cuser.userid, cuser.username); + i = ch - strlen(genbuf); + if (i >= 0) + i = (i >> 1) + 1; + else + { + genbuf[ch] = '\0'; + i = 1; + } + memset(data, ' ', i); + data[i] = '\0'; + + sprintf(mid_line, "\033[1;46;37m �ͤѻ��a \033[45m%s%s�j" + " �P %s%s\033[0m", 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; + + clear(); + move(i, 0); + outs(mid_line); + move(0, 0); + + add_io(fd, 0); + + while (1) + { + ch = igetkey(); + if (ch == I_OTHERDATA) + { + datac = recv(fd, data, sizeof(data), 0); + if (datac <= 0) + break; + for (i = 0; i < datac; i++) + do_talk_char(&itswin, data[i]); + } + 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) + fprintf(log, "%c", (ch == Ctrl('M')) ? '\n' : (char) *data); + do_talk_char(&mywin, *data); + } + } + if (log) + fclose(log); + + add_io(0, 0); + close(fd); + + if (flog) + { + char ans[4]; + extern screenline_t *big_picture; + extern unsigned char scr_lns; + int i; + + time(&now); + fprintf(flog, "\n\033[33;44m���O�e�� [%s] ... \033[m\n", + Cdatelite(&now)); + for (i = 0; i < scr_lns; i++) + fprintf(flog, "%.*s\n", big_picture[i].len, big_picture[i].data); + fclose(flog); + more(fpath, NA); + getdata(b_lines - 1, 0, "�M��(C) ���ܳƧѿ�(M). (C/M)?[C]", + ans, 4, LCECHO); + if (*ans == 'm') + { + fileheader_t mymail; + char title[128]; + + sethomepath(genbuf, cuser.userid); + stampfile(genbuf, &mymail); + mymail.savemode = 'H'; /* hold-mail flag */ + mymail.filemode = FILE_READ; + strcpy(mymail.owner, "[��.��.��]"); + sprintf(mymail.title, "��ܰO�� \033[1;36m(%s)\033[m", + getuserid(currutmp->destuid)); + sethomedir(title, cuser.userid); + Rename(fpath, genbuf); + append_record(title, &mymail, sizeof(mymail)); + } + else + unlink(fpath); + flog = 0; + } + setutmpmode(XINFO); +} + +#define lockreturn(unmode, state) if(lockutmpmode(unmode, state)) return + +static void my_talk(userinfo_t * uin, int fri_stat) { + int sock, msgsock, length, ch, error = 0; + struct sockaddr_in server; + pid_t pid; + char c; + char genbuf[4]; + + unsigned char mode0 = currutmp->mode; + + ch = uin->mode; + strcpy(currauthor, uin->userid); + + 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)) || + uin->lockmode == M_FIVE || uin->lockmode == CHC) + { + outs("�H�a�b����"); + } + else if (!HAS_PERM(PERM_SYSOP) && + ( + ((fri_stat& HRM) && !(fri_stat& HFM)) || + ((!uin->pager) && !(fri_stat & HFM)) + ) + ) + { + outs("��������I�s���F"); + } + else if (!HAS_PERM(PERM_SYSOP) && + ( + ((fri_stat & HRM) && !(fri_stat& HFM)) || + uin->pager == 2 + ) + ) + { + outs("���ޱ��I�s���F"); + } + else if (!HAS_PERM(PERM_SYSOP) && + !(fri_stat & HFM) && uin->pager == 4) + { + outs("���u�����n�ͪ��I�s"); + } + else if (!(pid = uin->pid) /*|| (kill(pid, 0) == -1) */ ) + { +// resetutmpent(); + outs(msg_usr_left); + } + else + { + showplans(uin->userid); + getdata(2, 0, "�n�M�L(�o) (T)�ͤ�(F)�U���l��(P)���d��" + "(C)�U�H��(D)�U�t��(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 'p': + reload_chicken(); + getuser(uin->userid); + if (uin->lockmode == CHICKEN || currutmp->lockmode == CHICKEN) + error = 1; + if (!cuser.mychicken.name[0] || !xuser.mychicken.name[0]) + error = 2; + if (error) + { + outmsg(error == 2 ? "�ëD��H���i�d��" : + "���@�誺�d�����b�ϥΤ�"); + bell(); + refresh(); + sleep(1); + return; + } + uin->sig = SIG_PK; + break; + default: + return; + } + + uin->turn = 1; + currutmp->turn = 0; + strcpy(uin->mateid, currutmp->userid); + strcpy(currutmp->mateid, uin->userid); + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) + { + perror("sock err"); + unlockutmpmode(); + return; + } + 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; + } + length = sizeof(server); + if (getsockname(sock, (struct sockaddr *) &server, &length) < 0) + { + close(sock); + perror("sock name err"); + unlockutmpmode(); + return; + } + currutmp->sockactive = YEA; + currutmp->sockaddr = server.sin_port; + currutmp->destuid = uin->uid; + setutmpmode(PAGE); + uin->destuip = currutmp - &utmpshm->uinfo[0]; + if(pid > 0) kill(pid, SIGUSR1); + clear(); + prints("���I�s %s.....\n��J Ctrl-D ����....", uin->userid); + + listen(sock, 1); + add_io(sock, 5); + while (1) + { + ch = igetch(); + if (ch == I_TIMEOUT) + { + ch = uin->mode; + if (!ch && uin->chatid[0] == 1 && + uin->destuip == currutmp - &utmpshm->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; + outmsg("�H�a�b����"); + pressanykey(); + unlockutmpmode(); + return; + } + else + { +#ifdef linux + add_io(sock, 20); /* added for linux... achen */ +#endif + move(0, 0); + outs("�A"); + bell(); + + uin->destuip = currutmp - &utmpshm->uinfo[0]; + if(pid <= 0 || kill(pid, SIGUSR1) == -1) + { +#ifdef linux + add_io(sock, 20); /* added 4 linux... achen */ +#endif + outmsg(msg_usr_left); + refresh(); + pressanykey(); + unlockutmpmode(); + return; + } + continue; + } + } + + if (ch == I_OTHERDATA) + break; + + if (ch == '\004') + { + add_io(0, 0); + close(sock); + currutmp->sockactive = currutmp->destuid = 0; + unlockutmpmode(); + return; + } + } + + msgsock = accept(sock, (struct sockaddr *) 0, (int *) 0); + if (msgsock == -1) + { + perror("accept"); + unlockutmpmode(); + return; + } + add_io(0, 0); + close(sock); + currutmp->sockactive = NA; + read(msgsock, &c, sizeof c); + + if (c == 'y') + { + sprintf(save_page_requestor, "%s (%s)", + uin->userid, uin->username); + /* gomo */ + switch (uin->sig) + { + case SIG_DARK: + main_dark(msgsock, uin); + break; + case SIG_PK: + chickenpk(msgsock); + break; + case SIG_GOMO: + gomoku(msgsock); + break; + case SIG_CHC: + chc(msgsock); + 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() { + clear(); + + outs("\033[36m�i ��Ѩϥλ��� �j\033[m\n\n" + "(��)(e) �������} (h) �ݨϥλ���\n" + "(��)/(��)(n) �W�U���� (TAB) �����ƧǤ覡\n" + "(PgUp)(^B) �W����� ( )(PgDn)(^F) �U�����\n" + "(Hm)/($)(Ed) ��/�� (S) " + "�ӷ�/�n�ʹy�z/���Z ����\n" + "(m) �H�H (q/c) " + "�d�ߺ���/�d��\n" + "(r) �\\Ū�H�� (l) �ݤW�����T\n" + "(f) ����/�n�ͦC�� (�Ʀr) ���ܸӨϥΪ�\n" + "(p) �����I�s�� (g/i) ����/�����߱�\n" + "(a/d/o) �n�� �W�[/�R��/�ק� (/)(s) ����ID/�ʺٷj�M"); + + if (HAS_PERM(PERM_PAGE)) + { + outs("\n\n\033[36m�i ��ͱM���� �j\033[m\n\n" + "(��)(t)(Enter) ��L���o���\n" + "(w) ���u Call in\n" + "(b) ��n�ͼs�� (�@�w�n�b�n�ͦC����)\n" + "(^R) �Y�ɦ^�� (���H Call in �A��)"); + } + + if (HAS_PERM(PERM_SYSOP)) + { + outs("\n\n\033[36m�i �����M���� �j\033[m\n\n"); + if (HAS_PERM(PERM_SYSOP)) + outs("(u)/(H) �]�w�ϥΪ̸��/�������μҦ�\n"); + outs("(R)/(K) �d�ߨϥΪ̪��u��m�W/���a�J��X�h\n"); + } + pressanykey(); +} + +static int listcuent(userinfo_t * uentp) { + if((!uentp->invisible || HAS_PERM(PERM_SYSOP) || HAS_PERM(PERM_SEECLOAK))) + AddNameList(uentp->userid); + return 0; +} + +static void creat_list() { + CreateNameList(); + apply_ulist(listcuent); +} + +static int search_pickup(int num, int actor, pickup_t pklist[]) { + char genbuf[IDLEN + 2]; + + move(1, 0); + creat_list(); + namecomplete(msg_uid, genbuf); + if (genbuf[0]) + { + int n = (num + 1) % actor; + while (n != num) + { + if (!strcasecmp(pklist[n].ui->userid, genbuf)) + return n; + if (++n >= actor) + n = 0; + } + } + return -1; +} + +/* Kaede show friend description */ +static char *friend_descript(char *uident) { + static char *space_buf = " "; + static char desc_buf[80]; + char fpath[80], name[IDLEN + 2], *desc, *ptr; + int len, flag; + FILE *fp; + char genbuf[200]; + + setuserfile(fpath, friend_file[0]); + + if ((fp = fopen(fpath, "r"))) + { + sprintf(name, "%s ", uident); + len = strlen(name); + desc = genbuf + 13; + + while ((flag = (int) fgets(genbuf, STRLEN, fp))) + { + if (!memcmp(genbuf, name, len)) + { + if ((ptr = strchr(desc, '\n'))) + ptr[0] = '\0'; + if (desc) + break; + } + } + fclose(fp); + if (desc && flag) + strcpy(desc_buf, desc); + else + return space_buf; + + return desc_buf; + } + else + return space_buf; +} + +static char *descript(int show_mode, userinfo_t * uentp, time_t diff, + fromcache_t * fcache) { + switch (show_mode) + { + case 1: + return friend_descript(uentp->userid); + case 0: + return (((uentp->pager != 2 && uentp->pager != 3 && diff) || + HAS_PERM(PERM_SYSOP)) ? +#ifdef WHERE + uentp->from_alias ? fcache->replace[uentp->from_alias] : + uentp->from +#else + uentp->from +#endif + : "*"); + case 2: + sprintf(description, "%3d/%3d/%3d", uentp->five_win, + uentp->five_lose, uentp->five_tie); + description[20] = 0; + return description; + default: + syslog(LOG_WARNING, "damn!!! what's wrong?? show_mode = %d", + show_mode); + return ""; + } +} + +static int pickup_user_cmp(time_t now, int sortedway, int cmp_fri, + pickup_t pklist[], int *bfriends_number, int *ifh_number, + int *hfm_number,int *irh_number, char *keyword) +{ + int i, fri_stat, is_friend, count=0, diff; + userinfo_t *uentp; + for (i=0;i<utmpshm->number;i++) + { + uentp = (utmpshm->sorted[utmpshm->currsorted][sortedway][i]); + if (!uentp || !uentp->pid) continue; + fri_stat = friend_stat(currutmp, uentp); + if(uentp->uid==currutmp->uid) + fri_stat = fri_stat|IFH|HFM; + is_friend = (fri_stat & IRH) && !(fri_stat & IFH) ? 0 : + fri_stat & ST_FRIEND; + if (!isvisible_stat(currutmp, uentp, fri_stat) || + ((cmp_fri==1 && !is_friend) || + (cmp_fri==-1 && is_friend)) || + (keyword[0] && !strcasestr(uentp->username,keyword)) + ) continue; + if (bfriends_number && fri_stat & IBH) (*bfriends_number)++; + if (ifh_number && fri_stat & IFH) (*ifh_number)++; + if (hfm_number && fri_stat & HFM) (*hfm_number)++; + if (irh_number && fri_stat & IRH) (*irh_number)++; +#ifdef SHOW_IDLE_TIME + diff = now - uentp->lastact; +#ifdef DOTIMEOUT + /* prevent fault /dev mount from kicking out users */ + if ((diff > curr_idle_timeout + 10) && + (diff < 60 * 60 * 24 * 5)) + { + if ((uentp->pid <= 0 || kill(uentp->pid, SIGHUP) == -1) && + (errno == ESRCH)) + purge_utmp(uentp); + continue; + } +#endif + pklist[count].idle = diff; +#endif + pklist[count].friend = fri_stat; + pklist[count].ui = uentp; + count++; + } + return count; +} + +static int cmputmpfriend(const void *i, const void *j) +{ + if((((pickup_t*)j)->friend&ST_FRIEND)==(((pickup_t*)i)->friend&ST_FRIEND)) + return strcasecmp( ((pickup_t*)i)->ui->userid, + ((pickup_t*)j)->ui->userid); + else + return (((pickup_t*)j)->friend&ST_FRIEND) - + (((pickup_t*)i)->friend&ST_FRIEND); +} + +static void pickup_user() { + static int real_name = 0; + static int show_mode = 0; + static int show_uid = 0; + static int show_board = 0; + static int show_pid = 0; + static int num = 0; + char genbuf[200]; + +#ifdef WHERE + extern struct fromcache_t *fcache; +#endif + + register userinfo_t *uentp; + register pid_t pid0 = 0; /* Ptt �w�� */ + register int id0 = 0; /* US_PICKUP�ɪ���Х� */ + register int state = US_PICKUP, ch; + register int actor = 0, head, foot; + int fri_stat, bfriends_number, ifh_number, irh_number, hfm_number; + int savemode = currstat; + int i, sortedway; /* �u�Oloop���Ψ� */ + time_t diff, freshtime; + pickup_t pklist[USHM_SIZE]; /* parameter Ptt�� */ +/* num : �{�b����Ц� */ +/* foot: �������}�} */ + char buf[20],keyword[13]=""; /* actor:�@���h��user */ + char pagerchar[5] = "* -Wf"; + char *msg_pickup_way[PICKUP_WAYS] = + { + "��! �B��", + "���ͥN��", + "���ͰʺA", + "�o�b�ɶ�", + "�Ӧۦ��", + "���l�� ", +// "�k�h�u��" + }; + char *MODE_STRING[MAX_SHOW_MODE] = + { + "�G�m", + "�n�ʹy�z", + "���l�Ѿ��Z" + }; + char + *Mind[] = + {" ", + "^-^", "^_^", "Q_Q", "@_@", "/_\\", "=_=", "-_-", "-.-", ">_<", + "-_+", "!_!", "o_o", "z_Z", "O_O", "O.O", "$_$", "^*^", "O_<", + "��!", "��!", "�s!", "��!", ":) ", ":( ", ":~ ", ":q ", ":O ", + ":D ", ":p ", ";) ", ":> ", ";> ", ":< ", ":)~", ":D~", ">< ", + "^^;", "^^|", "��;", NULL}; + + while (1) + { + if (utmpshm->uptime > freshtime || state == US_PICKUP || + state ==US_RESORT) + { + state = US_PICKUP; + time(&freshtime); + ifh_number=hfm_number=irh_number=bfriends_number = actor = ch = 0; + if(pickup_way==0) + sortedway=0; + else + sortedway=pickup_way-1; + + //qsort(pklist,actor,sizeof(pickup_t),cmputmpfriend); + if(pickup_way==0 || (cuser.uflag & FRIEND_FLAG)) + { + actor=pickup_user_cmp(freshtime, sortedway, 1, + pklist, &bfriends_number, &ifh_number, &hfm_number, + NULL,keyword); + if(sortedway==0) + qsort(pklist,actor,sizeof(pickup_t),cmputmpfriend); + if(!(cuser.uflag & FRIEND_FLAG)) + actor=pickup_user_cmp(freshtime, sortedway, -1, + pklist+actor, NULL, NULL, NULL, &irh_number, + keyword); + } + else + { + actor=pickup_user_cmp(freshtime, sortedway, 0, + pklist, &bfriends_number, &ifh_number, &hfm_number, + &irh_number, keyword); + } + + + if (!actor) + { + if(keyword[0]) + { + mprints(b_lines-1,0, + "�j�M�������H !!"); + keyword[0]=0; + pressanykey(); + continue; + } + getdata(b_lines - 1, 0, + "�A���B���٨S�W���A�n�ݬݤ@����Ͷ�(Y/N)�H[Y]", + genbuf, 4, LCECHO); + if (genbuf[0] != 'n') + { + cuser.uflag &= ~FRIEND_FLAG; + continue; + } + return; + } + } + if (state >= US_ACTION) + { + showtitle((cuser.uflag & FRIEND_FLAG) ? "�n�ͦC��" : "���", + BBSName); + prints(" �ƧǡG[%s] �W���H�ơG%-4d\033[1;32m�ڪ��B�͡G%-3d" + "\033[33m�P�ڬ��͡G%-3d\033[36m�O�͡G%-4d\033[31m�a�H�G" + "%-2d\033[m\n" + "\033[7m %s P%c�N�� %-17s%-17s%-13s%-10s\033[m\n", + msg_pickup_way[pickup_way], actor, ifh_number, + hfm_number, bfriends_number, irh_number, + show_uid ? "UID" : "No.", + (HAS_PERM(PERM_SEECLOAK) || HAS_PERM(PERM_SYSOP)) ? 'C' : ' ', + real_name ? "�m�W" : "�ʺ�", + MODE_STRING[show_mode], + show_board ? "Board" : "�ʺA", + show_pid ? " PID" : "�Ƶ� �o�b" + ); + } + else + { + move(3, 0); + clrtobot(); + } + if (pid0) + for (ch = 0; ch < actor; ch++) + { + if (pid0 == (pklist[ch].ui)->pid && + id0 == 256 * pklist[ch].ui->userid[0] + + pklist[ch].ui->userid[1]) + { + num = ch; + } + } + if (num < 0) + num = 0; + else if (num >= actor) + num = actor - 1; + head = (num / p_lines) * p_lines; + foot = head + p_lines; + if (foot > actor) + foot = actor; + for (ch = head; ch < foot; ch++) + { + uentp = pklist[ch].ui; + + if (!uentp->pid) + { + prints("%5d < ������..>\n",ch); + continue; + } +#ifdef SHOW_IDLE_TIME + diff = pklist[ch].idle; + if (diff > 59990) diff = 59990; /* Doma: �H�K�@�j�ꪺ�o�b�ɶ� */ + if (diff > 0) + sprintf(buf, "%3ld'%02ld", diff / 60, diff % 60); + else + buf[0] = '\0'; +#else + buf[0] = '\0'; +#endif + i = pklist[ch].friend; +#ifdef SHOWPID + if (show_pid) + sprintf(buf, "%6d", uentp->pid); +#endif + if (PERM_HIDE(uentp)) + state = 9; + else if(currutmp == uentp) + state =10; + else if(i & IRH && !(i & IFH)) + state = 8; + else + state =(i&ST_FRIEND)>>2; + diff = uentp->pager & !(i&HRM); + prints("%5d %c%c%s%-13s%-17.16s\033[m%-17.16s%-13.13s" + "\33[33m%-4.4s\33[m%s\n", +#ifdef SHOWUID + show_uid ? uentp->uid : +#endif + (ch + 1), + (i & HRM) ? 'X' : + pagerchar[uentp->pager % 5], + (uentp->invisible ? ')' : ' '), + fcolor[state], + /* %s */ + uentp->userid, + + /* %-13s �ʺ� */ +#ifdef REALINFO + real_name ? uentp->realname : +#endif + uentp->username, + /* %-17.16s �G�m */ + descript(show_mode, uentp, diff, fcache), + + /* %-17.16s �ݪO */ +#ifdef SHOWBOARD + show_board ? (uentp->brc_id == 0 ? "" : + bcache[uentp->brc_id - 1].brdname) : +#endif + /* %-13.13s */ + modestring(uentp, 0), + /* %4s �Ƶ� */ + ((uentp->userlevel & PERM_VIOLATELAW) ? "�q�r" : + (uentp->birth ? "�جP" : + Mind[uentp->mind])), + /* %s �o�b */ + buf); + } + if (state == US_PICKUP) + continue; + + move(b_lines, 0); + outs("\033[31;47m(TAB/f)\033[30m�Ƨ�/�n�� \033[31m(t)\033[30m��� " + "\033[31m(a/d/o)\033[30m��� \033[31m(q)\033[30m�d�� " + "\033[31m(w)\033[30m���y \033[31m(m)\033[30m�H�H \033[31m(h)" + "\033[30m�u�W���U \033[m"); + state = 0; + while (!state) + { + ch = cursor_key(num + 3 - head, 0); + if (ch == KEY_RIGHT || ch == '\n' || ch == '\r') + ch = 't'; + + switch (ch) + { + case KEY_LEFT: + case 'e': + case 'E': + if(!keyword[0]) return; + keyword[0]=0; + state = US_PICKUP; + break; + + case KEY_TAB: + pickup_way = (pickup_way + 1) % PICKUP_WAYS; + state = US_RESORT; + num = 0; + break; + + case KEY_DOWN: + case 'n': + case 'j': + if (++num < actor) + { + if (num >= foot) + state = US_REDRAW; + break; + } + case '0': + case KEY_HOME: + num = 0; + if (head) + state = US_REDRAW; + break; + case 'H': + if (HAS_PERM(PERM_SYSOP)) + { + currutmp->userlevel ^= PERM_DENYPOST; + state = US_REDRAW; + } + break; + case 'D': + if (HAS_PERM(PERM_SYSOP)) + { + char buf[100]; + + sprintf(buf, "�N�� [%s]�G", currutmp->userid); + if (!getdata(1, 0, buf, currutmp->userid, IDLEN + 1, + DOECHO)) + strcpy(currutmp->userid, cuser.userid); + state = US_REDRAW; + } + break; + case 'F': + if (HAS_PERM(PERM_SYSOP)) + { + char buf[100]; + + sprintf(buf, "�G�m [%s]�G", currutmp->from); + if (!getdata(1, 0, buf, currutmp->from, 17, DOECHO)) + strncpy(currutmp->from, fromhost, 23); + state = US_REDRAW; + } + break; + case 'C': +#if !HAVE_FREECLOAK + if (HAS_PERM(PERM_CLOAK)) +#endif + { + currutmp->invisible ^= 1; + state = US_REDRAW; + } + break; + case ' ': + case KEY_PGDN: + case Ctrl('F'): + if (foot < actor) + { + num += p_lines; + state = US_REDRAW; + break; + } + if (head) + num = 0; + state = US_PICKUP; + break; + case KEY_UP: + case 'k': + if (--num < head) + { + if (num < 0) + { + num = actor - 1; + if (actor == foot) + break; + } + state = US_REDRAW; + } + break; + case KEY_PGUP: + case Ctrl('B'): + case 'P': + if (head) + { + num -= p_lines; + state = US_REDRAW; + break; + } + + case KEY_END: + case '$': + num = actor - 1; + if (foot < actor) + state = US_REDRAW; + break; + + case '/': + getdata_buf(b_lines-1,0,"�п�J�ʺ�����r:",keyword, 12, + DOECHO); + state = US_PICKUP; + break; + case 's': + 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, actor - 1)) >= 0) + num = tmp; + state = US_REDRAW; + } + break; +#ifdef REALINFO + case 'R': /* ��ܯu��m�W */ + if (HAS_PERM(PERM_SYSOP)) + real_name ^= 1; + state = US_PICKUP; + break; +#endif +#ifdef SHOWUID + case 'U': + if (HAS_PERM(PERM_SYSOP)) + show_uid ^= 1; + state = US_PICKUP; + break; +#endif +#ifdef SHOWBOARD + case 'Y': + if (HAS_PERM(PERM_SYSOP)) + show_board ^= 1; + state = US_PICKUP; + break; +#endif +#ifdef SHOWPID + case '#': + if (HAS_PERM(PERM_SYSOP)) + show_pid ^= 1; + state = US_PICKUP; + break; +#endif + + case 'b': /* broadcast */ + if (cuser.uflag & FRIEND_FLAG || HAS_PERM(PERM_SYSOP)) + { + int actor_pos = actor; + char ans[4]; + + state = US_PICKUP; + if (!getdata(0, 0, "�s���T��:", genbuf, 60, DOECHO)) + break; + if (getdata(0, 0, "�T�w�s��? [Y]", ans, 4, LCECHO) && + *ans == 'n') + break; + while (actor_pos) + { + uentp = pklist[--actor_pos].ui; + fri_stat = pklist[actor_pos].friend; + if (uentp->pid && + currpid != uentp->pid && + uentp->pid > 0 && kill(uentp->pid, 0) != -1 && + (HAS_PERM(PERM_SYSOP) || + (uentp->pager != 3 && + (uentp->pager != 4 || fri_stat & HFM)))) + my_write(uentp->pid, genbuf, uentp->userid, HAS_PERM(PERM_SYSOP) ? 3 : 1); + } + } + break; + case 'S': /* ��ܦn�ʹy�z */ + show_mode = (++show_mode) % MAX_SHOW_MODE; + state = US_PICKUP; + break; + case 'u': /* �u�W�ק��� */ + case 'K': /* ���a�J��X�h */ + if (!HAS_PERM(PERM_ACCOUNTS)) + continue; + state = US_ACTION; + break; + case 'i': + state = US_ACTION; + break; + case Ctrl('S'): + state = US_ACTION; + break; + case 't': + case 'w': + if (!(cuser.userlevel & PERM_LOGINOK)) + continue; + state = US_ACTION; + break; + case 'a': + case 'd': + case 'o': + case 'f': + case 'g': + if (!HAS_PERM(PERM_LOGINOK)) + /* ���U�~�� Friend */ + break; + if (ch == 'f') + { + cuser.uflag ^= FRIEND_FLAG; + state = US_PICKUP; + break; + } + state = US_ACTION; + break; + case 'q': + case 'c': + case 'm': + case 'r': + case 'l': + /* guest �u�� query */ + if (!cuser.userlevel && ch != 'q' && ch != 'l') + break; + case 'h': + state = US_ACTION; + break; + case 'p': + if (HAS_PERM(PERM_BASIC)) + { + t_pager(); + state = US_REDRAW; + } + break; + case 'W': + { + int tmp; + char *wm[3] = {"�@��", "�i��", "����"}; + tmp = cuser.uflag2 & WATER_MASK; + cuser.uflag2 -= tmp; + tmp = (tmp + 1) % 3; + cuser.uflag2 |= tmp; + prints("������ %s ���y�Ҧ�", wm[tmp]); + refresh(); + sleep(1); + state = US_REDRAW; + } + default: /* refresh screen */ + state = US_REDRAW; + } + } + + if (state != US_ACTION) + { + pid0 = 0; + continue; + } + + /* Ptt decide cur */ + uentp = pklist[num].ui; + fri_stat = friend_stat(currutmp, uentp); + pid0 = uentp->pid; + id0 = 256 * uentp->userid[0] + uentp->userid[1]; + + if (ch == 'w') + { + if ((uentp->pid != currpid) && + (HAS_PERM(PERM_SYSOP) || + (uentp->pager != 3 && + (fri_stat & HFM || uentp->pager != 4)))) + { + cursor_show(num + 3 - head, 0); + sprintf(genbuf, "Call-In %s �G", uentp->userid); + my_write(uentp->pid, genbuf, uentp->userid, 0); + } + } + else if (ch == 'l') + { /* Thor: �� Last call in */ + t_display(); + } + else + { + switch (ch) + { + case 'r': + m_read(); + break; + case 'g': /* give money */ + move(b_lines - 2, 0); + if (strcmp(uentp->userid, cuser.userid)) + { + sprintf(genbuf, "�n�� %s �h�ֿ��O? ", uentp->userid); + outs(genbuf); + if (getdata(b_lines - 1, 0, "[�Ȧ���b]:", genbuf, 7, + LCECHO)) + { + clrtoeol(); + if ((ch = atoi(genbuf)) <= 0) + break; + reload_money(); + if (ch > cuser.money) + outs("\033[41m �{������~~\033[m"); + else + { + deumoney(uentp->uid, ch); + sprintf(genbuf, "\033[44m ��..�ٳѤU %d ��.." + "\033[m", demoney(-1*ch)); + outs(genbuf); + sprintf(genbuf, "%s\t��%s\t%d\t%s", cuser.userid, + uentp->userid, ch, + ctime(&currutmp->lastact)); + log_file(FN_MONEY, genbuf); + mail_redenvelop(cuser.userid, uentp->userid, ch, 'Y'); + } + } + else + { + clrtoeol(); + outs("\033[41m �������! \033[m"); + } + } + else + outs("\033[33m �ۤv���ۤv? �A��..\033[m"); + refresh(); + sleep(1); + break; +#ifdef SHOWMIND + case 'i': + move(3,0); + clrtobot(); + for (i = 1; Mind[i]!=NULL; i++) + { + move(5+(i-1)/7,((i-1)%7)*10); + prints("%2d: %s",i,Mind[i]); + } + getdata(b_lines - 1, 0, "�A�{�b���߱� 0:�L q���� [q]:", + genbuf, 3, LCECHO); + if (genbuf[0] && genbuf[0] != 'q') + currutmp->mind=atoi(genbuf)%i; + state = US_REDRAW; + break; +#endif + case 'a': + friend_add(uentp->userid, FRIEND_OVERRIDE); + friend_load(); + state = US_PICKUP; + break; + case 'd': + friend_delete(uentp->userid, FRIEND_OVERRIDE); + friend_load(); + state = US_PICKUP; + break; + case 'o': + t_override(); + state = US_PICKUP; + break; + case 'K': + if (uentp->pid > 0 && kill(uentp->pid, 0) != -1) + { + move(1, 0); + clrtobot(); + move(2, 0); + my_kick(uentp); + state = US_PICKUP; + } + break; + case 'm': + stand_title("�H �H"); + prints("[�H�H] ���H�H�G%s", uentp->userid); + my_send(uentp->userid); + break; + case 'q': + strcpy(currauthor, uentp->userid); + my_query(uentp->userid); + break; + case 'c': + chicken_query(uentp->userid); + break; + case 'u': /* Thor: �i�u�W�d�ݤέק�ϥΪ� */ + { + int id; + userec_t muser; + + strcpy(currauthor, uentp->userid); + stand_title("�ϥΪ̳]�w"); + move(1, 0); + if ((id = getuser(uentp->userid))) + { + memcpy(&muser, &xuser, sizeof(muser)); + user_display(&muser, 1); + uinfo_query(&muser, 1, id); + } + } + break; + + case 'h': /* Thor: �� Help */ + t_showhelp(); + break; + + case 't': + if (uentp->pid != currpid && + (strcmp(uentp->userid, cuser.userid))) + { + move(1, 0); + clrtobot(); + move(3, 0); + my_talk(uentp, fri_stat); + state = US_PICKUP; + } + break; + } + } + setutmpmode(savemode); + } +} + +int t_users() { + int destuid0 = currutmp->destuid; + int mode0 = currutmp->mode; + int stat0 = currstat; + + setutmpmode(LUSERS); + pickup_user(); + currutmp->mode = mode0; + currutmp->destuid = destuid0; + currstat = stat0; + return 0; +} + +int t_pager() { + currutmp->pager = (currutmp->pager + 1) % 5; + return 0; +} + +int t_idle() { + int destuid0 = currutmp->destuid; + int mode0 = currutmp->mode; + int stat0 = currstat; + char genbuf[20]; + char buf[80], passbuf[PASSLEN]; + + 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') + currutmp->destuid = genbuf[0] - '0'; + else + currutmp->destuid = 0; + + if (currutmp->destuid == 6) + if (!cuser.userlevel || + !getdata(b_lines - 1, 0, "�o�b���z�ѡG", currutmp->chatid, 11, + DOECHO)) + currutmp->destuid = 0; + do + { + move(b_lines - 2, 0); + clrtoeol(); + sprintf(buf, "(��w�ù�)�o�b��]: %s", (currutmp->destuid != 6) ? + IdleTypeTable[currutmp->destuid] : currutmp->chatid); + outs(buf); + refresh(); + getdata(b_lines - 1, 0, MSG_PASSWD, passbuf, PASSLEN, 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() { + char uident[STRLEN]; + + stand_title("�d���d��"); + usercomplete(msg_uid, uident); + if (uident[0]) + chicken_query(uident); + return 0; +} + +int t_query() { + char uident[STRLEN]; + + stand_title("�d�ߺ���"); + usercomplete(msg_uid, uident); + if (uident[0]) + my_query(uident); + return 0; +} + +int t_talk() { + 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"); + creat_list(); + namecomplete(msg_uid, uident); + if (uident[0] == '\0') + return 0; + + move(3, 0); + if (!(tuid = searchuser(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)); + + return 0; +} + +/* ���H�Ӧ���l�F�A�^���I�s�� */ +static userinfo_t *uip; +void talkreply() { + struct hostent *h; + char buf[4]; + struct sockaddr_in sin; + char genbuf[200]; + int a, sig = currutmp->sig; + + talkrequest = NA; + uip = &utmpshm->uinfo[currutmp->destuip]; + sprintf(page_requestor, "%s (%s)", uip->userid, uip->username); + currutmp->destuid = uip->uid; + currstat = XMODE; /* �קK�X�{�ʵe */ + + clear(); + + prints("\n\n"); + 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) \033[1;33m�ڦۤv��J�z�Ѧn�F...\033[m\n"); + prints(" (1) %s�H����100�Ȩ��" + " (2) %s�H����1000�Ȩ��..\n\n", sig_des[sig], sig_des[sig]); + + getuser(uip->userid); + currutmp->msgs[0].pid = uip->pid; + strcpy(currutmp->msgs[0].userid, uip->userid); + strcpy(currutmp->msgs[0].last_call_in, "�I�s�B�I�s�Ať��Ц^�� (Ctrl-R)"); + prints("���Ӧ� [%s]�A�@�W�� %d ���A�峹 %d �g\n", + uip->from, xuser.numlogins, xuser.numposts); + showplans(uip->userid); + show_last_call_in(0); + + sprintf(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, 4, LCECHO); + + if (uip->mode != PAGE) + { + sprintf(genbuf, "%s�w����I�s�A��Enter�~��...", page_requestor); + getdata(0, 0, genbuf, buf, 4, LCECHO); + return; + } + currutmp->msgcount = 0; + strcpy(save_page_requestor, page_requestor); + memset(page_requestor, 0, sizeof(page_requestor)); + if (!(h = gethostbyname("localhost"))) + { + perror("gethostbyname"); + return; + } + memset(&sin, 0, sizeof(sin)); + sin.sin_family = h->h_addrtype; + memcpy(&sin.sin_addr, h->h_addr, h->h_length); + sin.sin_port = uip->sockaddr; + a = socket(sin.sin_family, SOCK_STREAM, 0); + if ((connect(a, (struct sockaddr *) &sin, sizeof(sin)))) + { + perror("connect err"); + return; + } + if (!buf[0] || !strchr("yabcdef12", buf[0])) + buf[0] = 'n'; + write(a, buf, 1); + if (buf[0] == 'f' || buf[0] == 'F') + { + if (!getdata(b_lines, 0, "�����]�G", genbuf, 60, DOECHO)) + strcpy(genbuf, "���i�D�A�� !! ^o^"); + write(a, genbuf, 60); + } + uip->destuip = currutmp - &utmpshm->uinfo[0]; + if (buf[0] == 'y') + switch (sig) + { + case SIG_DARK: + main_dark(a, uip); + break; + case SIG_PK: + chickenpk(a); + break; + case SIG_GOMO: + gomoku(a); + break; + case SIG_CHC: + chc(a); + break; + case SIG_TALK: + default: + do_talk(a); + } + else + close(a); + clear(); +} + +/* ���ͰʺA²�� */ +/* not used +static int shortulist(userinfo_t * uentp) { + static int lineno, fullactive, linecnt; + static int moreactive, page, num; + char uentry[50]; + int state; + + if (!lineno) + { + lineno = 3; + page = moreactive ? (page + p_lines * 3) : 0; + linecnt = num = moreactive = 0; + move(1, 70); + prints("Page: %d", page / (p_lines) / 3 + 1); + move(lineno, 0); + } + + if (uentp == NULL) + { + int finaltally; + + clrtoeol(); + move(++lineno, 0); + clrtobot(); + finaltally = fullactive; + lineno = fullactive = 0; + return finaltally; + } + if ((!HAS_PERM(PERM_SYSOP) && + !HAS_PERM(PERM_SEECLOAK) && + uentp->invisible) || + ((friend_stat(currutmp, uentp) & HRM) && + !HAS_PERM(PERM_SYSOP))) + { + if (lineno >= b_lines) + return 0; + if (num++ < page) + return 0; + memset(uentry, ' ', 25); + uentry[25] = '\0'; + } + else + { + fullactive++; + if (lineno >= b_lines) + { + moreactive = 1; + return 0; + } + if (num++ < page) + return 0; + + state = (currutmp == uentp) ? 10 : + (friend_stat(currutmp,uentp)&ST_FRIEND)>>2; + + if (PERM_HIDE(uentp)) + state = 9; + + sprintf(uentry, "%s%-13s%c%-10s%s ", fcolor[state], + uentp->userid, uentp->invisible ? '#' : ' ', + modestring(uentp, 1), state ? "\033[0m" : ""); + } + if (++linecnt < 3) + { + strcat(uentry, "�x"); + outs(uentry); + } + else + { + outs(uentry); + linecnt = 0; + clrtoeol(); + move(++lineno, 0); + } + return 0; +} +*/ diff --git a/mbbsd/term.c b/mbbsd/term.c new file mode 100644 index 00000000..61a0128d --- /dev/null +++ b/mbbsd/term.c @@ -0,0 +1,144 @@ +/* $Id: term.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <termios.h> +#include <string.h> +#include <syslog.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +int tgetent(const char *bp, char *name); +char *tgetstr(const char *id, char **area); +int tgetflag(const char *id); +int tgetnum(const char *id); +int tputs(const char *str, int affcnt, int (*putc)(int)); +char *tparm(const char *str, ...); +char *tgoto(const char *cap, int col, int row); + +static struct termios tty_state, tty_new; + +/* ----------------------------------------------------- */ +/* basic tty control */ +/* ----------------------------------------------------- */ +void init_tty() { + 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) + +char *clearbuf = "\33[H\33[J"; +int clearbuflen = 6; + +char *cleolbuf = "\33[K"; +int cleolbuflen = 3; + +char *scrollrev = "\33M"; +int scrollrevlen = 2; + +char *strtstandout = "\33[7m"; +int strtstandoutlen = 4; + +char *endstandout = "\33[m"; +int endstandoutlen = 3; + +int t_lines = 24; +int b_lines = 23; +int p_lines = 20; +int t_columns = 80; + +int automargins = 1; + +static char *outp; +static int *outlp; + + +static int outcf(int ch) { + if(*outlp < TERMCOMSIZE) { + (*outlp)++; + *outp++ = ch; + } + return 0; +} + +extern screenline_t *big_picture; + +static void term_resize(int sig) { + struct winsize newsize; + screenline_t *new_picture; + + signal(SIGWINCH, SIG_IGN); /* Don't bother me! */ + ioctl(0, TIOCGWINSZ, &newsize); + if(newsize.ws_row > t_lines) { + new_picture = (screenline_t *)calloc(newsize.ws_row, + sizeof(screenline_t)); + if(new_picture == NULL) { + syslog(LOG_ERR, "calloc(): %m"); + return; + } + free(big_picture); + big_picture = new_picture; + } + + t_lines=newsize.ws_row; + b_lines=t_lines-1; + p_lines=t_lines-4; + + signal(SIGWINCH, term_resize); +} + +int term_init() { + signal(SIGWINCH, term_resize); + return YEA; +} + +char term_buf[32]; + +void do_move(int destcol, int destline) { + char buf[16], *p; + + sprintf(buf, "\33[%d;%dH", destline + 1, destcol + 1); + for(p = buf; *p; p++) + ochar(*p); +} + +void save_cursor() { + ochar('\33'); + ochar('7'); +} + +void restore_cursor() { + ochar('\33'); + ochar('8'); +} + +void change_scroll_range(int top, int bottom) { + char buf[16], *p; + + sprintf(buf, "\33[%d;%dr", top + 1, bottom + 1); + for(p = buf; *p; p++) + ochar(*p); +} + +void scroll_forward() { + ochar('\33'); + ochar('D'); +} diff --git a/mbbsd/toolkit.c b/mbbsd/toolkit.c new file mode 100644 index 00000000..81a0d6f0 --- /dev/null +++ b/mbbsd/toolkit.c @@ -0,0 +1,14 @@ +/* $Id: toolkit.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <ctype.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" + +unsigned StringHash(unsigned char *s) { + unsigned int v=0; + while(*s) { + v = (v << 8) | (v >> 24); + v ^= toupper(*s++); /* note this is case insensitive */ + } + return (v * 2654435769UL) >> (32 - HASH_BITS); +} diff --git a/mbbsd/topsong.c b/mbbsd/topsong.c new file mode 100644 index 00000000..d3a65447 --- /dev/null +++ b/mbbsd/topsong.c @@ -0,0 +1,79 @@ +/* $Id: topsong.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "proto.h" + +#define MAX_SONGS 300 +#define QCAST int (*)(const void *, const void *) + +typedef struct songcmp_t { + char name[100]; + char cname[100]; + long int count; +} songcmp_t; + +static long int totalcount=0; + +static int count_cmp(songcmp_t *b, songcmp_t *a) { + return (a->count - b->count); +} + +int topsong() { + more(FN_TOPSONG,YEA); + return 0; +} + +static int strip_blank(char *cbuf, char *buf) { + for(; *buf; buf++) + if(*buf != ' ') + *cbuf++ = *buf; + *cbuf = 0; + return 0; +} + +void sortsong() { + 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; + while(fgets(buf, 200, fp)) { + strtok(buf, "\n\r"); + strip_blank(cbuf, buf); + if(!cbuf[0] || !isprint2(cbuf[0])) + continue; + + for(n = 0; n < MAX_SONGS && songs[n].name[0]; n++) + if(!strcmp(songs[n].cname,cbuf)) + break; + strcpy(songs[n].name, buf); + strcpy(songs[n].cname, cbuf); + songs[n].count++; + totalcount++; + } + qsort(songs, MAX_SONGS, sizeof(songcmp_t), (QCAST)count_cmp); + fprintf(fo, + " \033[36m�w�w\033[37m�W��\033[36m�w�w�w�w�w�w\033[37m�q" + " �W\033[36m�w�w�w�w�w�w�w�w�w�w�w\033[37m����\033[36m" + "�w�w\033[32m�@%ld��\033[36m�w�w\033[m\n", totalcount); + for(n = 0; n < 100 && songs[n].name[0]; n++) { + fprintf(fo, " %5d. %-38.38s %4ld \033[32m[%.2f]\033[m\n", n + 1, + songs[n].name, songs[n].count, + (float)songs[n].count/totalcount); + } + fclose(fp); + fclose(fo); +} diff --git a/mbbsd/uptime b/mbbsd/uptime new file mode 100644 index 00000000..4f8281fb --- /dev/null +++ b/mbbsd/uptime @@ -0,0 +1,23 @@ +cache.c: if(fcache->busystate) +cache.c: fcache->busystate = 1; +cache.c: bzero(fcache->domain, sizeof fcache->domain); +cache.c: fcache->top=0; +cache.c: sscanf(buf,"%s",fcache->domain[fcache->top]); +cache.c: po = buf + strlen(fcache->domain[fcache->top]); +cache.c: strncpy(fcache->replace[fcache->top],po,49); +cache.c: fcache->replace[fcache->top] +cache.c: [strlen(fcache->replace[fcache->top])-1] = 0; +cache.c: (fcache->top)++; +cache.c: if(fcache->top == MAX_FROM) +cache.c: fcache->max_user=0; +cache.c: fcache->uptime = fcache->touchtime; +cache.c: fcache->busystate = 0; +cache.c: if(fcache->touchtime == 0) +cache.c: fcache->touchtime = 1; +cache.c: while(fcache->uptime < fcache->touchtime) +mbbsd.c: for (j = 0; j < fcache->top; j++){ +mbbsd.c: char *token = strtok (fcache->domain[j], "&"); +mbbsd.c: if ((a = utmpshm->number) > fcache->max_user){ +mbbsd.c: fcache->max_user = a; +mbbsd.c: fcache->max_time = now; +talk.c: uentp->from_alias ? fcache->replace[uentp->from_alias] : diff --git a/mbbsd/user.c b/mbbsd/user.c new file mode 100644 index 00000000..41aacfa9 --- /dev/null +++ b/mbbsd/user.c @@ -0,0 +1,980 @@ +/* $Id: user.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "perm.h" +#include "modes.h" +#include "proto.h" + +extern int numboards; +extern boardheader_t *bcache; +extern char *loginview_file[NUMVIEWFILE][2]; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern time_t login_start_time; +extern char *msg_uid; +extern int usernum; +extern char *msg_sure_ny; +extern userinfo_t *currutmp; +extern int showansi; +extern char reset_color[]; +extern char *fn_proverb; +extern char *fn_plans; +extern char *msg_del_ok; +extern char *fn_register; +extern char *msg_nobody; +extern userec_t cuser; +extern userec_t xuser; + +static char *sex[8] = { + MSG_BIG_BOY, MSG_BIG_GIRL, MSG_LITTLE_BOY, MSG_LITTLE_GIRL, + MSG_MAN, MSG_WOMAN, MSG_PLANT, MSG_MIME +}; + +int u_loginview() { + int i; + unsigned int pbits = cuser.loginview; + char choice[5]; + + clear(); + move(4,0); + for(i = 0; i < NUMVIEWFILE ; i++) + prints(" %c. %-20s %-15s \n", 'A' + i, + loginview_file[i][1],((pbits >> i) & 1 ? "��" : "��")); + + clrtobot(); + while(getdata(b_lines - 1, 0, "�Ы� [A-N] �����]�w�A�� [Return] �����G", + choice, 3, LCECHO)) { + i = choice[0] - 'a'; + if(i >= NUMVIEWFILE || i < 0) + bell(); + else { + pbits ^= (1 << i); + move( i + 4 , 28 ); + prints((pbits >> i) & 1 ? "��" : "��"); + } + } + + if(pbits != cuser.loginview) { + cuser.loginview = pbits ; + passwd_update(usernum, &cuser); + } + return 0; +} + +void user_display(userec_t *u, int real) { + int diff = 0; + char genbuf[200]; + + clrtobot(); + prints( + " \033[30;41m�r�s�r�s�r�s\033[m \033[1;30;45m �� �� ��" + " �� �� " + " \033[m \033[30;41m�r�s�r�s�r�s\033[m\n"); + prints(" �N���ʺ�: %s(%s)\n" + " �u��m�W: %s\n" + " �~�����}: %s\n" + " �q�l�H�c: %s\n" + " �� �O: %s\n" + " �Ȧ�b��: %ld �Ȩ�\n", + u->userid, u->username, u->realname, 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" + " �����Ҹ�: %s\n" + " ������X: %010d\n" + " �� ��: %02i/%02i/%02i\n" + " �p���W�r: %s\n", + get_num_records(genbuf, sizeof(fileheader_t)), + u->exmailbox, u->ident, u->mobile, + u->month, u->day, u->year % 100, u->mychicken.name); + prints(" ���U���: %s", ctime(&u->firstlogin)); + prints(" �e�����{: %s", ctime(&u->lastlogin)); + prints(" �e���I�q: %s", ctime(&u->lastsong)); + prints(" �W���峹: %d �� / %d �g\n", + u->numlogins, u->numposts); + + if(real) { + 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 = (time(0) - login_start_time) / 60; + prints(" ���d����: %d �p�� %2d ��\n", + diff / 60, diff % 60); + } + + /* Thor: �Q�ݬݳo�� user �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(" \033[30;41m�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\033[m"); + + outs((u->userlevel & PERM_LOGINOK) ? + "\n�z�����U�{�Ǥw�g�����A�w��[�J����" : + "\n�p�G�n���@�v���A�аѦҥ������G���z���U"); + +#ifdef NEWUSER_LIMIT + if((u->lastlogin - u->firstlogin < 3 * 86400) && !HAS_PERM(PERM_POST)) + outs("\n�s��W���A�T�ѫ�}���v��"); +#endif +} + +void mail_violatelaw(char* crime, char* police, char* reason, char* result){ + char genbuf[200]; + fileheader_t fhdr; + time_t now; + FILE *fp; + sprintf(genbuf, "home/%c/%s", crime[0], crime); + stampfile(genbuf, &fhdr); + if(!(fp = fopen(genbuf,"w"))) + return; + now = time(NULL); + fprintf(fp, "�@��: [Ptt�k�|]\n" + "���D: [���i] �H�k�P�M���i\n" + "�ɶ�: %s\n" + "\033[1;32m%s\033[m�P�M�G\n \033[1;32m%s\033[m" + "�]\033[1;35m%s\033[m�欰�A\n�H�ϥ������W�A�B�H\033[1;35m%s\033[m�A�S���q��" + "\n�Ш� PttLaw �d�߬����k�W��T�A�è� Play-Pay-ViolateLaw ú��@��", + ctime(&now), police, crime, reason, result); + fclose(fp); + sprintf(fhdr.title, "[���i] �H�k�P�M���i"); + strcpy(fhdr.owner, "[Ptt�k�|]"); + sprintf(genbuf, "home/%c/%s/.DIR", crime[0], crime); + append_record(genbuf, &fhdr, sizeof(fhdr)); +} + +static void violate_law(userec_t *u, int unum){ + char ans[4], ans2[4]; + char reason[128]; + move(1,0); + clrtobot(); + move(2,0); + prints("(1)Cross-post (2)�õo�s�i�H (3)�õo�s��H\n"); + prints("(4)���Z���W�ϥΪ� (8)��L�H�@��B�m�欰\n(9)�� id �欰\n"); + getdata(5, 0, "(0)����", + ans, 3, DOECHO); + switch(ans[0]){ + case '1': + sprintf(reason, "%s", "Cross-post"); + break; + case '2': + sprintf(reason, "%s", "�õo�s�i�H"); + break; + case '3': + sprintf(reason, "%s", "�õ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'){ + char src[STRLEN], dst[STRLEN]; + sprintf(src, "home/%c/%s", u->userid[0], u->userid); + sprintf(dst, "tmp/%s", u->userid); + Rename(src, dst); + log_usies("KILL", u->userid); + post_violatelaw(u->userid, cuser.userid, reason, "�尣 ID"); + u->userid[0] = '\0'; + setuserid(unum, u->userid); + passwd_update(unum, u); + } + else{ + u->userlevel |= PERM_VIOLATELAW; + u->vl_count ++; + passwd_update(unum, u); + post_violatelaw(u->userid, cuser.userid, reason, "�@��B��"); + mail_violatelaw(u->userid, cuser.userid, reason, "�@��B��"); + } + pressanykey(); +} + +extern char* str_permid[]; + +void uinfo_query(userec_t *u, int real, int unum) { + userec_t x; + register int i = 0, fail, mail_changed; + char ans[4], buf[STRLEN], *p; + char genbuf[200], reason[50]; + unsigned long int money = 0; + fileheader_t fhdr; + int flag = 0, temp = 0, money_change = 0; + time_t now; + + FILE *fp; + + fail = mail_changed = 0; + + memcpy(&x, u, sizeof(userec_t)); + getdata(b_lines - 1, 0, real ? + "(1)����(2)�]�K�X(3)�]�v��(4)��b��(5)��ID" + "(6)��/�_���d��(7)�f�P [0]���� " : + "�п�� (1)�ק��� (2)�]�w�K�X ==> [0]���� ", + ans, 3, DOECHO); + + if(ans[0] > '2' && !real) + ans[0] = '0'; + + if(ans[0] == '1' || ans[0] == '3') { + clear(); + i = 2; + move(i++, 0); + outs(msg_uid); + outs(x.userid); + } + + switch(ans[0]) { + case '7': + violate_law(&x, unum); + return; + case '1': + move(0, 0); + outs("�гv���ק�C"); + + getdata_buf(i++, 0," �� �� �G",x.username, 24, DOECHO); + if(real) { + getdata_buf(i++, 0, "�u��m�W�G", x.realname, 20, DOECHO); + getdata_buf(i++, 0, "�����Ҹ��G", x.ident, 11, DOECHO); + getdata_buf(i++, 0, "�~���a�}�G", x.address, 50, DOECHO); + } + sprintf(buf, "%010d", x.mobile); + getdata_buf(i++, 0, "������X�G", buf, 11, LCECHO); + x.mobile=atoi(buf); + getdata_str(i++, 0, "�q�l�H�c[�ܰʭn���s�{��]�G", buf, 50, DOECHO, + x.email); + if(strcmp(buf,x.email) && strchr(buf, '@')) { + strcpy(x.email,buf); + mail_changed = 1 - real; + } + + sprintf(genbuf, "%i", (u->sex + 1) % 8); + getdata_str(i++, 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) { + int len; + + sprintf(genbuf, "%02i/%02i/%02i", + u->month, u->day, u->year % 100); + len = getdata_str(i, 0, "�ͤ� ���/���/�褸�G", buf, 9, + DOECHO,genbuf); + if(len && len != 8) + continue; + if(!len) { + x.month = u->month; + x.day = u->day; + x.year = u->year; + } else if(len == 8) { + x.month = (buf[0] - '0') * 10 + (buf[1] - '0'); + x.day = (buf[3] - '0') * 10 + (buf[4] - '0'); + x.year = (buf[6] - '0') * 10 + (buf[7] - '0'); + } else + continue; + if(!real && (x.month > 12 || x.month < 1 || x.day > 31 || + x.day < 1 || x.year > 90 || x.year < 40)) + continue; + i++; + break; + } + if(real) { + unsigned long int l; + if(HAS_PERM(PERM_BBSADM)) { + sprintf(genbuf, "%d", x.money); + if(getdata_str(i++, 0,"�Ȧ�b��G", buf, 10, DOECHO,genbuf)) + if((l = atol(buf)) >= 0) { + if(l != x.money) { + money_change = 1; + money = x.money; + x.money = l; + } + } + } + sprintf(genbuf, "%d", x.exmailbox); + if(getdata_str(i++, 0,"�ʶR�H�c�ơG", buf, 4, DOECHO,genbuf)) + if((l = atol(buf)) >= 0) + x.exmailbox = (int)l; + + getdata_buf(i++, 0, "�{�Ҹ�ơG", x.justify, 44, DOECHO); + getdata_buf(i++, 0, "�̪���{�����G", x.lasthost, 16, DOECHO); + + sprintf(genbuf, "%d", x.numlogins); + if(getdata_str(i++, 0,"�W�u���ơG", buf, 10, DOECHO,genbuf)) + if((fail = atoi(buf)) >= 0) + x.numlogins = fail; + + sprintf(genbuf,"%d", u->numposts); + if(getdata_str(i++, 0, "�峹�ƥءG", buf, 10, DOECHO,genbuf)) + if((fail = atoi(buf)) >= 0) + x.numposts = fail; + sprintf(genbuf, "%d", u->vl_count); + if (getdata_str(i++, 0, "�H�k�O���G", buf, 10, DOECHO, genbuf)) + if ((fail = atoi(buf)) >= 0) + x.vl_count = fail; + + sprintf(genbuf, "%d/%d/%d", u->five_win, u->five_lose, + u->five_tie); + if(getdata_str(i++, 0, "���l�Ѿ��Z ��/��/�M�G", buf, 16, DOECHO, + genbuf)) + while(1) { + p = strtok(buf, "/\r\n"); + if(!p) break; + x.five_win = atoi(p); + p = strtok(NULL, "/\r\n"); + if(!p) break; + x.five_lose = atoi(p); + p = strtok(NULL, "/\r\n"); + if(!p) break; + x.five_tie = atoi(p); + break; + } + sprintf(genbuf, "%d/%d/%d", u->chc_win, u->chc_lose, u->chc_tie); + if(getdata_str(i++, 0, "�H�Ѿ��Z ��/��/�M�G", buf, 16, DOECHO, + genbuf)) + while(1) { + p = strtok(buf, "/\r\n"); + if(!p) break; + x.chc_win = atoi(p); + p = strtok(NULL, "/\r\n"); + if(!p) break; + x.chc_lose = atoi(p); + p = strtok(NULL, "/\r\n"); + if(!p) break; + x.chc_tie = atoi(p); + break; + } + fail = 0; + } + break; + + case '2': + i = 19; + if(!real) { + if(!getdata(i++, 0, "�п�J��K�X�G", buf, PASSLEN, NOECHO) || + !checkpasswd(u->passwd, buf)) { + outs("\n\n�z��J���K�X�����T\n"); + fail++; + break; + } + } + else{ + char witness[3][32]; + time_t now = time(NULL); + for(i=0;i<3;i++){ + if(!getdata(19+i, 0, "�п�J��U�ҩ����ϥΪ̡G", witness[i], 32, DOECHO)){ + outs("\n����J�h�L�k���\n"); + fail++; + break; + } + else if (!getuser(witness[i])){ + outs("\n�d�L���ϥΪ�\n"); + fail++; + break; + } + else if (now - xuser.firstlogin < 6*30*24*60*60){ + outs("\n���U���W�L�b�~�A�Э��s��J\n"); + i--; + } + } + if (i < 3) + break; + else + i = 20; + } + + if(!getdata(i++, 0, "�г]�w�s�K�X�G", buf, PASSLEN, NOECHO)) { + outs("\n\n�K�X�]�w����, �~��ϥ��±K�X\n"); + fail++; + break; + } + strncpy(genbuf, buf, PASSLEN); + + getdata(i++, 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'; + strncpy(x.passwd, genpasswd(buf), PASSLEN); + if (real) + x.userlevel &= (!PERM_LOGINOK); + break; + + case '3': + i = setperms(x.userlevel, str_permid); + if(i == x.userlevel) + fail++; + else { + flag=1; + temp=x.userlevel; + x.userlevel = i; + } + break; + + case '4': + i = QUIT; + break; + + case '5': + if (getdata_str(b_lines - 3, 0, "�s���ϥΪ̥N���G", genbuf, IDLEN + 1, + DOECHO,x.userid)) { + if(searchuser(genbuf)) { + outs("���~! �w�g���P�� ID ���ϥΪ�"); + fail++; + } else + strcpy(x.userid, genbuf); + } + break; + case '6': + if(x.mychicken.name[0]) + x.mychicken.name[0] = 0; + else + strcpy(x.mychicken.name,"[��]"); + break; + default: + return; + } + + if(fail) { + pressanykey(); + return; + } + + getdata(b_lines - 1, 0, msg_sure_ny, ans, 3, LCECHO); + if(*ans == 'y') { + if(flag) + post_change_perm(temp,i,cuser.userid,x.userid); + 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); + } + memcpy(u, &x, sizeof(x)); + if(mail_changed) { +#ifdef EMAIL_JUSTIFY + x.userlevel &= ~PERM_LOGINOK; + mail_justify(); +#endif + } + + if(i == QUIT) { + char src[STRLEN], dst[STRLEN]; + + sprintf(src, "home/%c/%s", x.userid[0], x.userid); + sprintf(dst, "tmp/%s", x.userid); + if(Rename(src, dst)) { + sprintf(genbuf, "/bin/rm -fr %s >/dev/null 2>&1", src); +/* do not remove + system(genbuf); +*/ + } + log_usies("KILL", x.userid); + x.userid[0] = '\0'; + setuserid(unum, x.userid); + } else + log_usies("SetUser", x.userid); + if(money_change) + setumoney(unum,x.money); + passwd_update(unum, &x); + now = time(0); + if(money_change) { + strcpy(genbuf, "boards/Security"); + stampfile(genbuf, &fhdr); + if(!(fp = fopen(genbuf,"w"))) + return; + + now = time(NULL); + fprintf(fp, "�@��: [�t�Φw����] �ݪO: Security\n" + "���D: [���w���i] �����ק�������i\n" + "�ɶ�: %s\n" + " ����\033[1;32m%s\033[m��\033[1;32m%s\033[m" + "�����q\033[1;35m%ld\033[m�令\033[1;35m%d\033[m", + ctime(&now), cuser.userid, x.userid, money, x.money); + + clrtobot (); + clear(); + while(!getdata(5, 0, "�п�J�z�ѥH�ܭt�d�G", reason, 60, DOECHO)); + + fprintf(fp, "\n \033[1;37m����%s�ק���z�ѬO�G%s\033[m", + cuser.userid, reason); + fclose(fp); + sprintf(fhdr.title, "[���w���i] ����%s�ק�%s�����i", cuser.userid, + x.userid); + strcpy(fhdr.owner, "[�t�Φw����]"); + append_record("boards/Security/.DIR", &fhdr, sizeof(fhdr)); + } + } +} + +int u_info() { + move(2, 0); + user_display(&cuser, 0); + uinfo_query(&cuser, 0, usernum); + strcpy(currutmp->realname, cuser.realname); + strcpy(currutmp->username, cuser.username); + return 0; +} + +int u_ansi() { + showansi ^= 1; + cuser.uflag ^= COLOR_FLAG; + outs(reset_color); + return 0; +} + +int u_cloak() { + outs((currutmp->invisible ^= 1) ? MSG_CLOAKED : MSG_UNCLOAK); + return XEASY; +} + +int u_switchproverb() { +/* char *state[4]={"�Υ\\��","�w�h��","�۩w��","SHUTUP"}; */ + char buf[100]; + + cuser.proverb =(cuser.proverb +1) %4; + setuserfile(buf,fn_proverb); + if(cuser.proverb==2 && dashd(buf)) { + FILE *fp = fopen(buf,"a"); + + fprintf(fp,"�y�k�ʪ��A��[�۩w��]�n�O�o�]�y�k�ʪ����e��!!"); + fclose(fp); + } + passwd_update(usernum, &cuser); + return 0; +} + +int u_editproverb() { + char buf[100]; + + setutmpmode(PROVERB); + setuserfile(buf,fn_proverb); + move(1,0); + clrtobot(); + outs("\n\n �Ф@��@��̧���J�Q�t�δ����A�����e,\n" + " �x�s��O�o�⪬�A�]�� [�۩w��] �~���@��\n" + " �y�k�ʳ̦h100��"); + pressanykey(); + vedit(buf,NA, NULL); + return 0; +} + +void showplans(char *uid) { + char genbuf[200]; + + sethomefile(genbuf, uid, fn_plans); + if(!show_file(genbuf, 7, MAX_QUERYLINES, ONLY_COLOR)) + prints("�m�ӤH�W���n%s �ثe�S���W��", uid); +} + +int showsignature(char *fname) { + FILE *fp; + char buf[256]; + int i, j; + char ch; + + clear(); + move(2, 0); + setuserfile(fname, "sig.0"); + j = strlen(fname) - 1; + + for(ch = '1'; ch <= '9'; ch++) { + fname[j] = ch; + if((fp = fopen(fname, "r"))) { + prints("\033[36m�i ñ�W��.%c �j\033[m\n", ch); + for(i = 0; i++ < MAX_SIGLINES && fgets(buf, 256, fp); outs(buf)); + fclose(fp); + } + } + return j; +} + +int u_editsig() { + int aborted; + char ans[4]; + int j; + char genbuf[200]; + + j = showsignature(genbuf); + + getdata(0, 0, "ñ�W�� (E)�s�� (D)�R�� (Q)�����H[Q] ", ans, 4, LCECHO); + + aborted = 0; + if(ans[0] == 'd') + aborted = 1; + if(ans[0] == 'e') + aborted = 2; + + if(aborted) { + if(!getdata(1, 0, "�п��ñ�W��(1-9)�H[1] ", ans, 4, 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() { + 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 u_editcalendar() { + char genbuf[200]; + + getdata(b_lines - 1, 0, "��ƾ� (D)�R�� (E)�s�� [Q]�����H[Q] ", + genbuf, 3, LCECHO); + + if(genbuf[0] == 'e') { + int aborted; + + setutmpmode(EDITPLAN); + setcalfile(genbuf, cuser.userid); + aborted = vedit(genbuf, NA, NULL); + if(aborted != -1) + outs("��ƾ��s����"); + pressanykey(); + return 0; + } else if(genbuf[0] == 'd') { + setcalfile(genbuf, cuser.userid); + unlink(genbuf); + outmsg("��ƾ�R������"); + } + return 0; +} + +/* �ϥΪ̶�g���U���� */ +static void getfield(int line, char *info, char *desc, char *buf, int len) { + char prompt[STRLEN]; + char genbuf[200]; + + sprintf(genbuf, "����]�w�G%-30.30s (%s)", buf, info); + move(line, 2); + outs(genbuf); + sprintf(prompt, "%s�G", desc); + if(getdata_str(line + 1, 2, prompt, genbuf, len, DOECHO, buf)) + strcpy(buf, genbuf); + move(line, 2); + prints("%s�G%s", desc, buf); + clrtoeol(); +} + +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 u_register() { + char rname[20], addr[50], ident[11], mobile[20]; + char phone[20], career[40], email[50],birthday[9],sex_is[2],year,mon,day; + char ans[3], *ptr; + FILE *fn; + time_t now; + char genbuf[200]; + + if(cuser.userlevel & PERM_LOGINOK) { + outs("�z�������T�{�w�g�����A���ݶ�g�ӽЪ�"); + return XEASY; + } + if((fn = fopen(fn_register, "r"))) { + while(fgets(genbuf, STRLEN, fn)) { + if((ptr = strchr(genbuf, '\n'))) + *ptr = '\0'; + if(strncmp(genbuf, "uid: ", 5) == 0 && + strcmp(genbuf + 5, cuser.userid) == 0) { + fclose(fn); + outs("�z�����U�ӽг�|�b�B�z���A�Э@�ߵ���"); + return XEASY; + } + } + fclose(fn); + } + + getdata(b_lines - 1, 0, "�z�T�w�n��g���U���(Y/N)�H[N] ", ans, 3, LCECHO); + if(ans[0] != 'y') + return FULLUPDATE; + + move(2, 0); + clrtobot(); + strcpy(ident, cuser.ident); + strcpy(rname, cuser.realname); + strcpy(addr, cuser.address); + strcpy(email, cuser.email); + sprintf(mobile,"0%09d",cuser.mobile); + sprintf(birthday, "%02i/%02i/%02i", + cuser.month, cuser.day, cuser.year % 100); + sex_is[0]=(cuser.sex % 8)+'1';sex_is[1]=0; + career[0] = phone[0] = '\0'; + while(1) { + clear(); + move(1, 0); + prints("%s(%s) �z�n�A�оڹ��g�H�U�����:", + cuser.userid, cuser.username); + do{ + getfield(3, "D120908396", "�����Ҹ�", ident, 11); + }while(removespace(ident)<10 || !isalpha(ident[0])); + do{ + getfield(5, "�ХΤ���", "�u��m�W", rname, 20); + }while(!removespace(rname) || isalpha(rname[0])); + do{ + getfield(7, "�Ǯըt�ũγ��¾��", "�A�ȳ��", career, 40); + }while(!removespace(career)); + do{ + getfield(9, "�]�A��ǩΪ��P���X", "�ثe���}", addr, 50); + }while(!(addr[0])); + do{ + getfield(11, "�]�A���~�����ϰ�X", "�s���q��", phone, 20); + }while(!removespace(phone)); + getfield(13, "�u��J�Ʀr �p:0912345678", "������X", mobile, 20); + while(1) { + int len; + + getfield(15,"���/���/�褸 �p:09/27/76","�ͤ�",birthday,9); + len = strlen(birthday); + if(!len) { + sprintf(birthday, "%02i/%02i/%02i", + cuser.month, cuser.day, cuser.year % 100); + mon = cuser.month; + day = cuser.day; + year = cuser.year; + } else if(len == 8) { + mon = (birthday[0] - '0') * 10 + (birthday[1] - '0'); + day = (birthday[3] - '0') * 10 + (birthday[4] - '0'); + year = (birthday[6] - '0') * 10 + (birthday[7] - '0'); + } else + continue; + if(mon > 12 || mon < 1 || day > 31 || day < 1 || year > 90 || + year < 40) + continue; + break; + } + getfield(17, "1.���� 2.�j�� ", "�ʧO", sex_is, 2); + getfield(19, "�����{�ҥ�", "E-Mail Address", email, 50); + + getdata(b_lines - 1, 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; + } + strcpy(cuser.ident, ident); + strcpy(cuser.realname, rname); + strcpy(cuser.address, addr); + strcpy(cuser.email, email); + cuser.mobile = atoi(mobile); + cuser.sex= (sex_is[0] - '1') % 8; + cuser.month = mon; + cuser.day = day; + cuser.year = year; + if((fn = fopen(fn_register, "a"))) { + now = time(NULL); + trim(career); + trim(addr); + trim(phone); + fprintf(fn, "num: %d, %s", usernum, ctime(&now)); + fprintf(fn, "uid: %s\n", cuser.userid); + fprintf(fn, "ident: %s\n", ident); + 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); + } + clear(); + move(9,3); + prints("�̫�Post�@�g\033[32m�ۧڤ��Ф峹\033[m���j�a�a�A" + "�i�D�Ҧ��Ѱ��Y\033[31m�ڨӰ�^$�C\\n\n\n\n"); + pressanykey(); + cuser.userlevel |= PERM_POST; + brc_initial("WhoAmI"); + set_board(); + do_post(); + cuser.userlevel &= ~PERM_POST; + return 0; +} + +/* �C�X�Ҧ����U�ϥΪ� */ +extern struct uhash_t *uhash; +static int usercounter, totalusers, showrealname; +static ushort u_list_special; + +static int u_list_CB(userec_t *uentp) { + static int i; + char permstr[8], *ptr; + register int level; + + if(uentp == NULL) { + move(2, 0); + clrtoeol(); + prints("\033[7m �ϥΪ̥N�� %-25s �W�� �峹 %s " + "�̪���{��� \033[0m\n", + showrealname ? "�u��m�W" : "�︹�ʺ�", + HAS_PERM(PERM_SEEULEVELS) ? "����" : ""); + i = 3; + return 0; + } + + if(bad_user_id(uentp->userid)) + return 0; + + if((uentp->userlevel & ~(u_list_special)) == 0) + return 0; + + if(i == b_lines) { + prints("\033[34;46m �w��� %d/%d �H(%d%%) \033[31;47m " + "(Space)\033[30m �ݤU�@�� \033[31m(Q)\033[30m ���} \033[m", + usercounter, totalusers, usercounter * 100 / totalusers); + i = igetch(); + if(i == 'q' || i == 'Q') + return QUIT; + i = 3; + } + if(i == 3) { + move(3, 0); + clrtobot(); + } + + level = uentp->userlevel; + strcpy(permstr, "----"); + if(level & PERM_SYSOP) + permstr[0] = 'S'; + else if(level & PERM_ACCOUNTS) + permstr[0] = 'A'; + else if(level & PERM_DENYPOST) + 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, + showrealname ? uentp->realname : uentp->username, + uentp->numlogins, uentp->numposts, + HAS_PERM(PERM_SEEULEVELS) ? permstr : "", ptr); + usercounter++; + i++; + return 0; +} + +int u_list() { + char genbuf[3]; + + setutmpmode(LAUSERS); + showrealname = u_list_special = usercounter = 0; + totalusers = uhash->number; + if(HAS_PERM(PERM_SEEULEVELS)) { + getdata(b_lines - 1, 0, "�[�� [1]�S������ (2)�����H", + genbuf, 3, DOECHO); + if(genbuf[0] != '2') + u_list_special = PERM_BASIC | PERM_CHAT | PERM_PAGE | PERM_POST | PERM_LOGINOK | PERM_BM; + } + if(HAS_PERM(PERM_CHATROOM) || HAS_PERM(PERM_SYSOP)) { + getdata(b_lines - 1, 0, "��� [1]�u��m�W (2)�ʺ١H", + genbuf, 3, DOECHO); + if(genbuf[0] != '2') + showrealname = 1; + } + u_list_CB(NULL); + if(passwd_apply(u_list_CB) == -1) { + outs(msg_nobody); + return XEASY; + } + move(b_lines, 0); + clrtoeol(); + prints("\033[34;46m �w��� %d/%d ���ϥΪ�(�t�ήe�q�L�W��) " + "\033[31;47m (�Ы����N���~��) \033[m", usercounter, totalusers); + egetch(); + return 0; +} diff --git a/mbbsd/var.c b/mbbsd/var.c new file mode 100644 index 00000000..7b07f63b --- /dev/null +++ b/mbbsd/var.c @@ -0,0 +1,268 @@ +/* $Id: var.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" + +char *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 */ + "���������~���H", /* PERM_ */ + "�S�Q��", /* PERM_ */ + "��ı����", /* PERM_VIEWSYSOP */ + "�[��ϥΪ̦���", /* PERM_LOGUSER */ + "��ذ��`��z�v", /* PERM_Announce */ + "������", /* PERM_RELATION */ + "�S�Ȳ�", /* PERM_SMG */ + "�{����", /* PERM_PRG */ + "���ʲ�", /* PERM_ACTION */ + "���u��", /* PERM_PAINT */ + "�ߪk��", /* PERM_LAW */ + "�p�ժ�", /* PERM_SYSSUBOP */ + "�@�ťD��", /* PERM_LSYSOP */ + "�ޢ���" /* PERM_PTT */ +}; + +char *str_permboard[] = { + "���i Zap", /* BRD_NOZAP */ + "���C�J�έp", /* BRD_NOCOUNT */ + "����H", /* BRD_NOTRAN */ + "�s�ժ�", /* BRD_GROUP */ + "���ê�", /* BRD_HIDE */ + "����(���ݳ]�w)", /* BRD_POSTMASK */ + "�ΦW��", /* BRD_ANONYMOUS */ + "�w�]�ΦW��", /* BRD_DEFAULTANONYMOUS */ + "�H�k��i���ݪ�", /* BRD_BAD */ + "�s�p�M�άݪ�", /* BRD_VOTEBOARD */ + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", + "�S�Q��", +}; + +int usernum; +pid_t currpid; /* current process ID */ +unsigned int currstat; +int currmode = 0; +int curredit = 0; +int showansi = 1; +int curr_idle_timeout = IDLE_TIMEOUT; +time_t login_start_time; +userec_t cuser; /* current user structure */ +userec_t xuser; /* lookup user structure */ +char quote_file[80] = "\0"; +char quote_user[80] = "\0"; +time_t paste_time; +char paste_title[STRLEN]; +char paste_path[256]; +int paste_level; +char currtitle[40] = "\0"; +char vetitle[40] = "\0"; +char currowner[IDLEN + 2] = "\0"; +char currauthor[IDLEN + 2] = "\0"; +char currfile[FNLEN]; /* current file name @ bbs.c mail.c */ +unsigned char currfmode; /* current file mode */ +char currboard[IDLEN + 2]; +int currbid; +unsigned int currbrdattr; +char currBM[IDLEN * 3 + 10]; +char reset_color[4] = "\033[m"; +char margs[64] = "\0"; /* main argv list*/ +crosspost_t postrecord; /* anti cross post */ + +/* global string variables */ +/* filename */ + +char *fn_passwd = FN_PASSWD; +char *fn_board = FN_BOARD; +char *fn_note_ans = FN_NOTE_ANS; +char *fn_register = "register.new"; +char *fn_plans = "plans"; +char *fn_writelog = "writelog"; +char *fn_talklog = "talklog"; +char *fn_overrides = FN_OVERRIDES; +char *fn_reject = FN_REJECT; +char *fn_canvote = FN_CANVOTE; +char *fn_notes = "notes"; +char *fn_water = FN_WATER; +char *fn_visable = FN_VISABLE; +char *fn_mandex = "/.Names"; +char *fn_proverb = "proverb"; + +/* are descript in userec.loginview */ + +char *loginview_file[NUMVIEWFILE][2] = { + {FN_NOTE_ANS ,"�IJ��W���y���O"}, + {FN_TOPSONG ,"�I�q�Ʀ�]" }, + {"etc/topusr" ,"�Q�j�Ʀ�]" }, + {"etc/topusr100" ,"�ʤj�Ʀ�]" }, + {"etc/birth.today" ,"����جP" }, + {"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��Ʀ�]"} +}; + +/* message */ +char *msg_seperator = MSG_SEPERATOR; +char *msg_mailer = MSG_MAILER; +char *msg_shortulist = MSG_SHORTULIST; + +char *msg_cancel = MSG_CANCEL; +char *msg_usr_left = MSG_USR_LEFT; +char *msg_nobody = MSG_NOBODY; + +char *msg_sure_ny = MSG_SURE_NY; +char *msg_sure_yn = MSG_SURE_YN; + +char *msg_bid = MSG_BID; +char *msg_uid = MSG_UID; + +char *msg_del_ok = MSG_DEL_OK; +char *msg_del_ny = MSG_DEL_NY; + +char *msg_fwd_ok = MSG_FWD_OK; +char *msg_fwd_err1 = MSG_FWD_ERR1; +char *msg_fwd_err2 = MSG_FWD_ERR2; + +char *err_board_update = ERR_BOARD_UPDATE; +char *err_bid = ERR_BID; +char *err_uid = ERR_UID; +char *err_filename = ERR_FILENAME; + +char *str_mail_address = "." BBSUSER "@" MYHOSTNAME; +char *str_new = "new"; +char *str_reply = "Re: "; +char *str_space = " \t\n\r"; +char *str_sysop = "SYSOP"; +char *str_author1 = STR_AUTHOR1; +char *str_author2 = STR_AUTHOR2; +char *str_post1 = STR_POST1; +char *str_post2 = STR_POST2; +char *BBSName = BBSNAME; + +/* #define MAX_MODES 78 */ +/* MAX_MODES is defined in common.h */ + +char *ModeTypeTable[MAX_MODES] = { + "�o�b", /* IDLE */ + "�D���", /* MMENU */ + "�t�κ��@", /* ADMIN */ + "�l����", /* MAIL */ + "��Ϳ��", /* TMENU */ + "�ϥΪ̿��", /* UMENU */ + "XYZ ���", /* XMENU */ + "�����ݪO", /* CLASS */ + "Play���", /* PMENU */ + "�s�S�O�W��", /* NMENU */ + "��tt�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�dzƤ�", /* 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�y���U��", /* EDITEXP */ + "�ӽ�IP��}", /* IPREG */ + "���줽��", /* NetAdm */ + "������~�{", /* DRINK */ + "�p���", /* CAL */ + "�s�y�y�k��", /* PROVERB */ + "���G��", /* ANNOUNCE */ + "��y����", /* EDNOTE */ + "�^�~½Ķ��", /* CDICT */ + "�˵��ۤv���~", /* LOBJ */ + "�I�q", /* OSONG */ + "���b���p��", /* CHICKEN */ + "���m��", /* TICKET */ + "�q�Ʀr", /* GUESSNUM */ + "�C�ֳ�", /* AMUSE */ + "�¥մ�", /* 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�X", /* DARK */ + "NBA�j�q��" /* TMPJACK */ + "��tt�d�]�t��", /* JCEE */ + "���s�峹" /* REEDIT */ +}; diff --git a/mbbsd/vice.c b/mbbsd/vice.c new file mode 100644 index 00000000..46f695d9 --- /dev/null +++ b/mbbsd/vice.c @@ -0,0 +1,151 @@ +/* $Id: vice.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" +extern int usernum; + +#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, sizeof(tbingo)); + 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], 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; +} +// Ptt: showfile ran_showfile more �T�̭n��X +static int ran_showfile(int y, int x, char *filename, int maxnum) { + FILE *fs; + char buf[512]; + + bzero(buf, sizeof(char) * 512); + sprintf(buf, "%s%d", filename, rand() % 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, 511, fs)) + prints("%s", buf); + + fclose(fs); + return 1; +} + +static int ran_showmfile(char *filename, int maxnum) { + char buf[256]; + + sprintf(buf, "%s%d", filename, rand() % maxnum + 1); + return more(buf, YEA); +} + +extern userec_t cuser; + +int vice_main() { + 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(); + prints("�o�@�����o�����X"); + while(fgets(serial, 15, fd)) { + if((ptr = strchr(serial,'\r'))) + *ptr = 0; + if(j == 0) + i++; + move(10 + i, 24 + j); + prints("%s", serial); + j += 9; + j %= 45; + } + getdata(8, 0, "��'c'�}�l����F(�άO���N�����})): ", ch, 2, 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 new file mode 100644 index 00000000..62916c99 --- /dev/null +++ b/mbbsd/vote.c @@ -0,0 +1,1068 @@ +/* $Id: vote.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <time.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/file.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +static int total; +extern int numboards; +extern boardheader_t *bcache; /* Thor: for speed up */ +extern char *err_board_update; +extern char *fn_board; +extern char *msg_seperator; +extern int t_lines, t_columns; /* Screen size / width */ +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern int currmode; +extern int usernum; +extern char currboard[]; /* name of currently selected board */ +extern userec_t cuser; + +static char STR_bv_control[] = "control"; /* �벼��� �ﶵ */ +static char STR_bv_desc[] = "desc"; /* �벼�ت� */ +static char STR_bv_ballots[] = "ballots"; +static char STR_bv_flags[] = "flags"; +static char STR_bv_comments[] = "comments"; /* �벼�̪��طN */ +static char STR_bv_limited[] = "limited"; /* �p�H�벼 */ +static char STR_bv_title[] = "vtitle"; + +static char STR_bv_results[] = "results"; + +static char STR_new_control[] = "control0"; /* �벼��� �ﶵ */ +static char STR_new_desc[] = "desc0"; /* �벼�ت� */ +static char STR_new_ballots[] = "ballots0"; +static char STR_new_flags[] = "flags0"; +static char STR_new_comments[] = "comments0"; /* �벼�̪��طN */ +static char STR_new_limited[] = "limited0"; /* �p�H�벼 */ +static char STR_new_title[] = "vtitle0"; + +int strip_ansi(char *buf, char *str, int mode) { + register int ansi, count = 0; + + for(ansi = 0; *str /*&& *str != '\n' */; str++) { + if(*str == 27) { + if(mode) { + if(buf) + *buf++ = *str; + count++; + } + ansi = 1; + } else if(ansi && strchr("[;1234567890mfHABCDnsuJKc=n", *str)) { + if((mode == NO_RELOAD && !strchr("c=n", *str)) || + (mode == ONLY_COLOR && strchr("[;1234567890m", *str))) { + if(buf) + *buf++ = *str; + count++; + } + if(strchr("mHn ", *str)) + ansi = 0; + } else { + ansi =0; + if(buf) + *buf++ = *str; + count++; + } + } + if(buf) + *buf = '\0'; + return count; +} + +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); + } +} + +static void b_count(char *buf, int counts[]) { + char inchar; + int fd; + + memset(counts, 0, 31 * sizeof(counts[0])); + total = 0; + if((fd = open(buf, O_RDONLY)) != -1) { + flock(fd, LOCK_EX); /* Thor: ����h�H�P�ɺ� */ + while(read(fd, &inchar, 1) == 1) { + counts[(int)(inchar - 'A')]++; + total++; + } + flock(fd, LOCK_UN); + close(fd); + } +} + + +static int b_nonzeroNum(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(char *bname, char *fname, char *fpath) { + register char *ip; + time_t dtime; + int fd, bid; + fileheader_t header; + + ip = fpath; + while(*(++ip)); + *ip++ = '/'; + + /* get a filename by timestamp */ + + dtime = time(0); + for(;;) { + sprintf(ip, "M.%ld.A", ++dtime); + fd = open(fpath, O_CREAT | O_EXCL | O_WRONLY, 0644); + if(fd >= 0) + break; + dtime++; + } + close(fd); + + log_usies("TESTfn", fname); + log_usies("TESTfp", fpath); + + unlink(fpath); + link(fname, fpath); + + /* append record to .DIR */ + + memset(&header, 0, sizeof(fileheader_t)); + strcpy(header.owner, "[�������l]"); + sprintf(header.title, "[%s] �ݪO �ﱡ����", bname); + { + register struct tm *ptime = localtime(&dtime); + + sprintf(header.date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday); + } + strcpy(header.filename, ip); + + strcpy(ip, ".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(boardheader_t *fh, int ind) { + FILE *cfp, *tfp, *frp, *xfp; + char *bname ; + char buf[STRLEN]; + char inbuf[80]; + int counts[31]; + int num ; + int junk; + char b_control[64]; + char b_newresults[64]; + char b_report[64]; + time_t closetime, now; + + fh->bvote--; + + if(fh->bvote==0) + fh->bvote=2; + else if(fh->bvote==2) + fh->bvote=1; + + if(ind) { + sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, ind); + sprintf(STR_new_control, "%s%d", STR_bv_control, ind); + sprintf(STR_new_desc, "%s%d", STR_bv_desc, ind); + sprintf(STR_new_flags, "%s%d", STR_bv_flags, ind); + sprintf(STR_new_comments, "%s%d", STR_bv_comments, ind); + sprintf(STR_new_limited, "%s%d", STR_bv_limited, ind); + sprintf(STR_new_title, "%s%d", STR_bv_title, ind); + } else { + strcpy(STR_new_ballots, STR_bv_ballots); + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_desc, STR_bv_desc); + strcpy(STR_new_flags, STR_bv_flags); + strcpy(STR_new_comments, STR_bv_comments); + strcpy(STR_new_limited, STR_bv_limited); + strcpy(STR_new_title, STR_bv_title); + } + + bname = fh->brdname; + + setbfile(buf, bname, STR_new_control); + cfp = fopen(buf,"r"); + fscanf(cfp, "%d\n%lu\n", &junk, &closetime); + fclose(cfp); + + setbfile(b_control, bname, "tmp"); + if(rename(buf, b_control) == -1) + return; + setbfile(buf, bname, STR_new_flags); + num = b_nonzeroNum(buf); + unlink(buf); + setbfile(buf, bname, STR_new_ballots); + b_count(buf, counts); + unlink(buf); + + setbfile(b_newresults, bname, "newresults"); + if((tfp = fopen(b_newresults, "w")) == NULL) + return; + + now = time(NULL); + setbfile(buf, bname, STR_new_title); + + if((xfp=fopen(buf,"r"))) { + fgets(inbuf, sizeof(inbuf), xfp); + fprintf(tfp, "%s\n�� �벼�W��: %s\n\n", msg_seperator, inbuf); + } + + fprintf(tfp, "%s\n�� �벼�����: %s\n\n�� �����D�شy�z:\n\n", + msg_seperator, ctime(&closetime)); + fh->vtime = now; + + setbfile(buf, bname, STR_new_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�� %d ��)\n", + num, junk); + while(fgets(inbuf, sizeof(inbuf), cfp)) { + inbuf[(strlen(inbuf) - 1)] = '\0'; + num = counts[inbuf[0] - 'A']; + fprintf(tfp, " %-42s %3d �� %02.2f%%\n", inbuf + 3, num, + (float)(num*100)/(float)(total)); + } + fclose(cfp); + } + unlink(b_control); + + fprintf(tfp, "%s\n�� �ϥΪ̫�ij�G\n\n", msg_seperator); + setbfile(buf, bname, STR_new_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); + } + sprintf(inbuf, "boards/%s", bname); + vote_report(bname, b_report, inbuf); + if(!(fh->brdattr &BRD_NOCOUNT)) { + sprintf(inbuf, "boards/%s", "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(boardheader_t *fh) { + FILE *cfp; + time_t closetime, now; + int i; + char buf[STRLEN]; + char temp[STRLEN]; + + now = time(NULL); + for(i = 0; i < 9; i++) { + if(i) + sprintf(STR_new_control, "%s%d", STR_bv_control, i); + else + strcpy(STR_new_control, STR_bv_control); + + setbfile(buf, fh->brdname, STR_new_control); + cfp = fopen(buf,"r"); + if (!cfp) + continue; + fgets(temp,sizeof(temp),cfp); + fscanf(cfp, "%lu\n", &closetime); + fclose(cfp); + if(closetime < now) + b_result_one(fh,i); + } +} + +static int b_close(boardheader_t *fh) { + time_t now; + now = time(NULL); + + if(fh->bvote == 2) { + if(fh->vtime < now - 3 * 86400) { + fh->bvote = 0; + return 1; + } + else + return 0; + } + b_result(fh); + return 1; +} + +int b_closepolls() { + static char *fn_vote_polling = ".polling"; + boardheader_t *fhp; + FILE *cfp; + time_t now; + int pos, dirty; + time_t last; + char timebuf[100]; + + now = time(NULL); +/* Edited by CharlieL for can't auto poll bug */ + + if((cfp = fopen(fn_vote_polling,"r"))) { + fgets(timebuf,100*sizeof(char),cfp); + sscanf(timebuf, "%lu", &last); + fclose(cfp); + if(last + 3600 >= now) + return 0; + } + + if((cfp = fopen(fn_vote_polling, "w")) == NULL) + return 0; + fprintf(cfp, "%lu\n%s\n", now, ctime(&now)); + fclose(cfp); + + dirty = 0; + for(fhp = bcache, pos = 1; pos <= numboards; fhp++, pos++) { + if(fhp->bvote && b_close(fhp)) { + if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) + outs(err_board_update); + dirty = 1; + } + } + if(dirty) /* vote flag changed */ + reset_board(pos); + + return 0; +} + +static int vote_view(char *bname, int index) { + boardheader_t *fhp; + FILE* fp; + char buf[STRLEN], genbuf[STRLEN], inbuf[STRLEN]; + struct stat stbuf; + int fd, num = 0, i, pos, counts[31]; + time_t closetime; + + if(index) { + sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, index); + sprintf(STR_new_control, "%s%d", STR_bv_control, index); + sprintf(STR_new_desc, "%s%d", STR_bv_desc, index); + sprintf(STR_new_flags, "%s%d", STR_bv_flags, index); + sprintf(STR_new_comments, "%s%d", STR_bv_comments, index); + sprintf(STR_new_limited, "%s%d", STR_bv_limited, index); + sprintf(STR_new_title, "%s%d", STR_bv_title, index); + } else { + strcpy(STR_new_ballots, STR_bv_ballots); + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_desc, STR_bv_desc); + strcpy(STR_new_flags, STR_bv_flags); + strcpy(STR_new_comments, STR_bv_comments); + strcpy(STR_new_limited, STR_bv_limited); + strcpy(STR_new_title, STR_bv_title); + } + + setbfile(buf, bname, STR_new_ballots); + if((fd = open(buf, O_RDONLY)) > 0) { + fstat(fd, &stbuf); + close(fd); + } else + stbuf.st_size = 0; + + setbfile(buf, bname, STR_new_title); + move(0, 0); + clrtobot(); + + if((fp = fopen(buf, "r"))) { + fgets(inbuf, sizeof(inbuf), fp); + prints("\n�벼�W��: %s", inbuf); + } + + setbfile(buf, bname, STR_new_control); + fp = fopen(buf, "r"); + fgets(inbuf, sizeof(inbuf), fp); + fscanf(fp, "%lu\n", &closetime); + + prints("\n�� �w���벼����: �C�H�̦h�i�� %d ��,�ثe�@�� %d ��,\n" + "�����벼�N������ %s", atoi(inbuf), stbuf.st_size, + ctime(&closetime)); + + /* Thor: �}�� ���� �w�� */ + setbfile(buf, bname, STR_new_flags); + num = b_nonzeroNum(buf); + + setbfile(buf, bname, STR_new_ballots); + b_count(buf, counts); + + prints("�@�� %d �H�벼\n", num); + total = 0; + + while(fgets(inbuf, sizeof(inbuf), fp)) { + inbuf[(strlen(inbuf) - 1)] = '\0'; + inbuf[30] = '\0'; /* truncate */ + i = inbuf[0] - 'A'; + num = counts[i]; + move(i % 15 + 6, i / 15 * 40); + prints(" %-32s%3d ��", inbuf, num); + total += num; + } + fclose(fp); + pos = getbnum(bname); + 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') { + setbfile(buf, bname, STR_new_control); + unlink(buf); + setbfile(buf, bname, STR_new_flags); + unlink(buf); + setbfile(buf, bname, STR_new_ballots); + unlink(buf); + setbfile(buf, bname, STR_new_desc); + unlink(buf); + setbfile(buf, bname, STR_new_limited); + unlink(buf); + setbfile(buf,bname, STR_new_title); + unlink(buf); + + if(fhp->bvote) + fhp->bvote--; + if (fhp->bvote == 2) + fhp->bvote = 1; + + 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(fhp,index); + if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) + outs(err_board_update); + + reset_board(pos); + } + return FULLUPDATE; +} + +static int vote_view_all(char *bname) { + int i; + int x = -1; + FILE *fp, *xfp; + char buf[STRLEN], genbuf[STRLEN]; + char inbuf[80]; + + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_title, STR_bv_title); + setbfile(buf, bname, STR_new_control); + move(0, 0); + if((fp=fopen(buf,"r"))) { + prints("(0) "); + x = 0; + fclose(fp); + + setbfile(buf, bname, STR_new_title); + if((xfp=fopen(buf,"r"))) + fgets(inbuf, sizeof(inbuf), xfp); + else + strcpy(inbuf, "�L���D"); + prints("%s\n", inbuf); + fclose(xfp); + } + + for(i = 1; i < 9; i++) { + sprintf(STR_new_control, "%s%d", STR_bv_control, i); + sprintf(STR_new_title, "%s%d", STR_bv_title, i); + setbfile(buf, bname, STR_new_control); + if((fp=fopen(buf,"r"))) { + prints("(%d) ", i); + x = i; + fclose(fp); + + setbfile(buf, bname, STR_new_title); + if((xfp=fopen(buf,"r"))) + fgets(inbuf, sizeof(inbuf), xfp); + else + strcpy(inbuf, "�L���D"); + prints("%s\n", inbuf); + fclose(xfp); + } + } + + if(x < 0) + return FULLUPDATE; + sprintf(buf, "�n�ݴX���벼 [%d] ", x); + + getdata(b_lines - 1, 0, buf, genbuf, 4, LCECHO); + + if(genbuf[0] < '0' || genbuf[0] > '8') + genbuf[0] = '0'+x; + + if(genbuf[0] != '0') + sprintf(STR_new_control, "%s%c", STR_bv_control, genbuf[0]); + else + strcpy(STR_new_control, STR_bv_control); + + setbfile(buf, bname, STR_new_control); + + if((fp=fopen(buf,"r"))) { + fclose(fp); + return vote_view(bname, genbuf[0] - '0'); + } + else + return FULLUPDATE; +} + +static int vote_maintain(char *bname) { + FILE *fp = NULL; + char inbuf[STRLEN], buf[STRLEN]; + int num = 0, aborted, pos, x, i; + time_t closetime; + boardheader_t *fhp; + char genbuf[4]; + + if(!(currmode & MODE_BOARD)) + return 0; + if((pos = getbnum(bname)) <= 0) + return 0; + + stand_title("�|��벼"); + fhp = bcache + pos - 1; + +/* CharlieL */ + if(fhp->bvote != 2 && fhp->bvote !=0) { + getdata(b_lines - 1, 0, + "(V)�[��ثe�벼 (M)�|��s�벼 (A)�����Ҧ��벼 (Q)�~�� [Q]", + genbuf, 4, LCECHO); + if(genbuf[0] == 'v') + return vote_view_all(bname); + else if(genbuf[0] == 'a') { + fhp->bvote=0; + + setbfile(buf, bname, STR_bv_control); + unlink(buf); + setbfile(buf, bname, STR_bv_flags); + unlink(buf); + setbfile(buf, bname, STR_bv_ballots); + unlink(buf); + setbfile(buf, bname, STR_bv_desc); + unlink(buf); + setbfile(buf, bname, STR_bv_limited); + unlink(buf); + setbfile(buf, bname, STR_bv_title); + unlink(buf); + + for(i = 1; i < 9; i++) { + sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, i); + sprintf(STR_new_control, "%s%d", STR_bv_control, i); + sprintf(STR_new_desc, "%s%d", STR_bv_desc, i); + sprintf(STR_new_flags, "%s%d", STR_bv_flags, i); + sprintf(STR_new_comments, "%s%d", STR_bv_comments, i); + sprintf(STR_new_limited, "%s%d", STR_bv_limited, i); + sprintf(STR_new_title, "%s%d", STR_bv_title, i); + + setbfile(buf, bname, STR_new_control); + unlink(buf); + setbfile(buf, bname, STR_new_flags); + unlink(buf); + setbfile(buf, bname, STR_new_ballots); + unlink(buf); + setbfile(buf, bname, STR_new_desc); + unlink(buf); + setbfile(buf, bname, STR_new_limited); + unlink(buf); + setbfile(buf, bname, STR_new_title); + unlink(buf); + } + if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1) + outs(err_board_update); + + return FULLUPDATE; + } else if(genbuf[0] != 'm' || fhp->bvote > 10) + return FULLUPDATE; + } + + strcpy(STR_new_control, STR_bv_control); + setbfile(buf,bname, STR_new_control); + x = 0; + while(x < 9 && (fp = fopen(buf,"r")) != NULL) { + fclose(fp); + x++; + sprintf(STR_new_control, "%s%d", STR_bv_control, x); + setbfile(buf, bname, STR_new_control); + } + if(fp) + fclose(fp); + if(x >=9) + return FULLUPDATE; + if(x) { + sprintf(STR_new_ballots, "%s%d", STR_bv_ballots,x); + sprintf(STR_new_control, "%s%d", STR_bv_control,x); + sprintf(STR_new_desc, "%s%d", STR_bv_desc,x); + sprintf(STR_new_flags, "%s%d", STR_bv_flags,x); + sprintf(STR_new_comments, "%s%d", STR_bv_comments,x); + sprintf(STR_new_limited, "%s%d", STR_bv_limited,x); + sprintf(STR_new_title, "%s%d", STR_bv_title,x); + } else { + strcpy(STR_new_ballots, STR_bv_ballots); + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_desc, STR_bv_desc); + strcpy(STR_new_flags, STR_bv_flags); + strcpy(STR_new_comments, STR_bv_comments); + strcpy(STR_new_limited, STR_bv_limited); + strcpy(STR_new_title, STR_bv_title); + } + clear(); + move(0,0); + prints("�� %d ���벼\n", x); + setbfile(buf, bname, STR_new_title); + getdata(4, 0, "�п�J�벼�W��", inbuf, 30, LCECHO); + if(inbuf[0]=='\0') + strcpy(inbuf,"�����W��"); + fp = fopen(buf, "w"); + fprintf(fp, "%s", inbuf); + fclose(fp); + + prints("��������}�l�s�覹�� [�벼�v��]"); + pressanykey(); + setbfile(buf, bname, STR_new_desc); + aborted = vedit(buf, NA, NULL); + if(aborted== -1) { + clear(); + outs("���������벼"); + pressanykey(); + return FULLUPDATE; + } + aborted = 0; + setbfile(buf, bname, STR_new_flags); + unlink(buf); + + getdata(4, 0, + "�O�_���w�벼�̦W��G(y)�s�y�i�벼�H���W��[n]����H�ҥi�벼:[N]", + inbuf, 2, LCECHO); + setbfile(buf, bname, STR_new_limited); + if(inbuf[0] == 'y') { + fp = fopen(buf, "w"); + fprintf(fp,"�����벼�]��"); + fclose(fp); + friend_edit(FRIEND_CANVOTE); + } else { + if(dashf(buf)) + unlink(buf); + } + clear(); + getdata(0, 0, "�����벼�i��X�� (�@��Q��)�H", inbuf, 4, DOECHO); + + closetime = atoi(inbuf); + if(closetime <= 0) + closetime = 1; + else if(closetime >10) + closetime = 10; + + closetime = closetime * 86400 + time(NULL); + setbfile(buf, bname, STR_new_control); + fp = fopen(buf, "w"); + fprintf(fp, "00\n%lu\n", closetime); + + outs("\n�Ш̧ǿ�J�ﶵ, �� ENTER �����]�w"); + num = 0; + while(!aborted) { + sprintf(buf, "%c) ", num + 'A'); + getdata((num % 15) + 2, (num / 15) * 40, buf, inbuf, 36, DOECHO); + if(*inbuf) { + fprintf(fp, "%1c) %s\n", (num+'A'), inbuf); + num++; + } + if((*inbuf == '\0' && num >= 1) || num == 30) + aborted = 1; + } + sprintf(buf, "�аݨC�H�̦h�i��X���H([1]��%d): ", num); + + getdata(t_lines-3, 0, buf, inbuf, 3, DOECHO); + + if(atoi(inbuf) <= 0 || atoi(inbuf) > num) + strcpy(inbuf,"1"); + + rewind(fp); + fprintf(fp, "%2d\n", MAX(1, atoi(inbuf))); + fclose(fp); + + if(fhp->bvote == 2) + fhp->bvote = 0; + else if(fhp->bvote == 1) + fhp->bvote = 2; + else if(fhp->bvote == 2) + fhp->bvote = 1; + + 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(char *bname, int index, char val) { + char buf[256], flag; + int fd, num, size; + + if(index) + sprintf(STR_new_flags, "%s%d", STR_bv_flags, index); + else + strcpy(STR_new_flags, STR_bv_flags); + + num = usernum - 1; + setbfile(buf, bname, STR_new_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 same(char compare, char list[], int num) { + int n; + int rep = 0; + + for(n = 0; n < num; n++) { + if(compare == list[n]) + rep = 1; + if(rep == 1) + list[n] = list[n + 1]; + } + return rep; +} + +static int user_vote_one(char *bname, int ind) { + FILE* cfp,*fcm; + char buf[STRLEN]; + boardheader_t *fhp; + int pos = 0, i = 0, count = 0, tickets, fd; + char inbuf[80], choices[31], vote[4], chosen[31]; + time_t closetime; + + if(ind) { + sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, ind); + sprintf(STR_new_control, "%s%d", STR_bv_control, ind); + sprintf(STR_new_desc, "%s%d", STR_bv_desc, ind); + sprintf(STR_new_flags, "%s%d", STR_bv_flags, ind); + sprintf(STR_new_comments, "%s%d", STR_bv_comments, ind); + sprintf(STR_new_limited, "%s%d", STR_bv_limited, ind); + } else { + strcpy(STR_new_ballots, STR_bv_ballots); + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_desc, STR_bv_desc); + strcpy(STR_new_flags, STR_bv_flags); + strcpy(STR_new_comments, STR_bv_comments); + strcpy(STR_new_limited, STR_bv_limited); + } + + setbfile(buf, bname, STR_new_control); + cfp = fopen(buf,"r"); + if(!cfp) + return FULLUPDATE; + + setbfile(buf, bname, STR_new_limited); /* Ptt */ + if(dashf(buf)) { + setbfile(buf, bname, FN_CANVOTE); + if(!belong(buf, cuser.userid)) { + fclose(cfp); + outs("\n\n�藍�_! �o�O�p�H�벼..�A�èS�����ܭ�!"); + pressanykey(); + return FULLUPDATE; + } else { + outs("\n\n���ߧA���ܦ����p�H�벼....<�����N���˵��������ܦW��>"); + pressanykey(); + more(buf, YEA); + } + } + if(vote_flag(bname, ind, '\0')) { + outs("\n\n�����벼�A�A�w��L�F�I"); + pressanykey(); + return FULLUPDATE; + } + + setutmpmode(VOTING); + setbfile(buf, bname, STR_new_desc); + more(buf, YEA); + + stand_title("�벼�c"); + if((pos = getbnum(bname)) <= 0) + return 0; + + fhp = bcache + pos - 1; + fgets(inbuf, sizeof(inbuf), cfp); + tickets = atoi(inbuf); + fscanf(cfp,"%lu\n", &closetime); + + prints("�벼�覡�G�T�w�n�z����ܫ�A��J��N�X(A, B, C...)�Y�i�C\n" + "�����벼�A�i�H�� %1d ���C" + "�� 0 �����벼 , 1 �����벼\n" + "�����벼�N������G%s \n", + tickets, ctime(&closetime)); + move(5, 0); + memset(choices, 0, sizeof(choices)); + memset(chosen , 0, sizeof(chosen)); + + while(fgets(inbuf, sizeof(inbuf), cfp)) { + move((count % 15) + 5, (count / 15) * 40); + prints( " %s", strtok(inbuf, "\n\0")); + choices[count++] = inbuf[0]; + } + fclose(cfp); + + while(1) { + vote[0] = vote[1] = '\0'; + move(t_lines - 2, 0); + prints("�A�٥i�H�� %2d ��", tickets - i); + getdata(t_lines - 4, 0, "��J�z�����: ", vote, 3, DOECHO); + *vote = toupper(*vote); + if(vote[0] == '0' || (!vote[0] && !i)) { + outs("�O���A�ӧ��!!"); + break; + } else if(vote[0] == '1' && i) + ; + else if(!vote[0]) + continue; + else if(index(choices, vote[0]) == NULL) /* �L�� */ + continue; + else if(same(vote[0], chosen, i)) { + move(((vote[0] - 'A') % 15) + 5, (((vote[0] - 'A')) / 15) * 40); + prints(" "); + i--; + continue; + } else { + if(i == tickets) + continue; + chosen[i] = vote[0]; + move(((vote[0]-'A') % 15) + 5, (((vote[0] - 'A')) / 15) * 40); + prints("*"); + i++; + continue; + } + + if(vote_flag(bname, ind, vote[0]) != 0) + prints("���Ч벼! �����p���C"); + else { + setbfile(buf, bname, STR_new_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++) + strcpy(mycomments[i], "\n"); + + flock(fd, LOCK_EX); + for(count = 0; count < 31; count++) { + if(chosen[count]) + write(fd, &chosen[count], 1); + } + 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], 74, + 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, STR_new_comments); + if(mycomments[0]) + if((fcm = fopen(b_comments, "a"))){ + fprintf(fcm, + "\033[36m���ϥΪ�\033[1;36m %s " + "\033[;36m����ij�G\033[m\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); + prints("�w�����벼�I\n"); + } + } + break; + } + pressanykey(); + return FULLUPDATE; +} + +static int user_vote(char *bname) { + int pos; + boardheader_t *fhp; + char buf[STRLEN]; + FILE* fp,*xfp; + int i, x = -1; + char genbuf[STRLEN]; + char inbuf[80]; + + if((pos = getbnum(bname)) <= 0) + return 0; + + fhp = bcache + pos - 1; + + move(0,0); + clrtobot(); + + if(fhp->bvote == 2 || fhp->bvote == 0) { + outs("\n\n�ثe�èS������벼�|��C"); + pressanykey(); + return FULLUPDATE; + } + + if(!HAS_PERM(PERM_LOGINOK)) { + outs("\n�藍�_! �z�����G�Q��, �٨S���벼�v��!"); + pressanykey(); + return FULLUPDATE; + } + + strcpy(STR_new_control, STR_bv_control); + strcpy(STR_new_title, STR_bv_title); + setbfile(buf, bname, STR_new_control); + move(0, 0); + if((fp = fopen(buf, "r"))) { + prints("(0) "); + x = 0; + fclose(fp); + + setbfile(buf, bname, STR_new_title); + if((xfp = fopen(buf,"r"))) + fgets(inbuf, sizeof(inbuf), xfp); + else + strcpy(inbuf, "�L���D"); + prints("%s\n", inbuf); + fclose(xfp); + } + + for(i = 1; i < 9; i++) { + sprintf(STR_new_control, "%s%d", STR_bv_control, i); + sprintf(STR_new_title, "%s%d", STR_bv_title, i); + setbfile(buf, bname, STR_new_control); + if((fp = fopen(buf, "r"))) { + prints("(%d) ", i); + x = i; + fclose(fp); + + setbfile(buf, bname, STR_new_title); + if((xfp = fopen(buf, "r"))) + fgets(inbuf, sizeof(inbuf), xfp); + else + strcpy(inbuf, "�L���D"); + prints("%s\n", inbuf); + fclose(xfp); + } + } + + if(x < 0) + return FULLUPDATE; + + sprintf(buf, "�n��X���벼 [%d] ", x); + + getdata(b_lines - 1, 0, buf, genbuf, 4, LCECHO); + + if(genbuf[0] < '0' || genbuf[0] > '8') + genbuf[0] = x + '0'; + + if(genbuf[0] != '0') + sprintf(STR_new_control, "%s%c", STR_bv_control, genbuf[0]); + else + strcpy(STR_new_control, STR_bv_control); + + setbfile(buf, bname, STR_new_control); + + if((fp = fopen(buf, "r"))){ + fclose(fp); + + return user_vote_one(bname, genbuf[0] - '0'); + } else + return FULLUPDATE; +} + +static int vote_results(char *bname) { + char buf[STRLEN]; + + setbfile(buf, bname, STR_bv_results); + if(more(buf, YEA) == -1) + outs("\n�ثe�S������벼�����G�C"); + return FULLUPDATE; +} + +int b_vote_maintain() { + return vote_maintain(currboard); +} + +int b_vote() { + return user_vote(currboard); +} + +int b_results() { + return vote_results(currboard); +} diff --git a/mbbsd/voteboard.c b/mbbsd/voteboard.c new file mode 100644 index 00000000..1286d986 --- /dev/null +++ b/mbbsd/voteboard.c @@ -0,0 +1,447 @@ +/* $Id: voteboard.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/file.h> +#include "config.h" +#include "pttstruct.h" +#include "modes.h" +#include "common.h" +#include "perm.h" +#include "proto.h" + +#define VOTEBOARD "NewBoard" + +extern char currboard[]; +extern int currbid; +extern boardheader_t *bcache; +extern int currmode; +extern userec_t cuser; + +void do_voteboardreply(fileheader_t *fhdr){ + char genbuf[1024]; + char reason[60]; + char fpath[80]; + char oldfpath[80]; + char opnion[10]; + char *ptr; + FILE *fo, *fp; + fileheader_t votefile; + int len; + int i, j; + int fd; + time_t endtime, now = time(NULL); + int hastime = 0; + + + clear(); + if(!(currmode & MODE_POST)) { + move(5, 10); + outs("�藍�_�A�z�ثe�L�k�b���o���峹�I"); + pressanykey(); + return; + } + + setbpath(fpath, currboard); + stampfile(fpath, &votefile); + + setbpath(oldfpath, currboard); + + strcat(oldfpath, "/"); + strcat(oldfpath, fhdr->filename); + + fp = fopen(oldfpath, "r"); + + len = strlen(cuser.userid); + + while(fgets(genbuf, 1024, fp)){ + if (!strncmp(genbuf, "�s�p�����ɶ�", 12)){ + hastime = 1; + ptr = strchr(genbuf, '('); + sscanf(ptr+1, "%ld", &endtime); + if (endtime < now){ + prints("�s�p�ɶ��w�L"); + pressanykey(); + fclose(fp); + return; + } + } + if (!strncmp(genbuf+4, cuser.userid, len)){ + move(5, 10); + prints("�z�w�g�s�p�L���g�F"); + opnion[0] = 'n'; + getdata(7, 0, "�n�ק�z���e���s�p�ܡH(Y/N) [N]", opnion, 3, LCECHO); + if (opnion[0] != 'y'){ + fclose(fp); + return; + } + strcpy(reason, genbuf+19); + } + } + fclose(fp); + + if((fd = open(oldfpath, O_RDONLY)) == -1) + return; + flock(fd, LOCK_EX); + + fo = fopen(fpath, "w"); + + if (!fo) + return; + i = 0; + while(fo){ + j = 0; + do{ + if (read(fd, genbuf+j, 1)<=0){ + flock(fd, LOCK_UN); + close(fd); + fclose(fo); + unlink(fpath); + return; + } + j++; + }while(genbuf[j-1] !='\n'); + genbuf[j] = '\0'; + i++; + if (!strncmp("----------", genbuf, 10)) + break; + if (i > 3) + prints(genbuf); + fprintf(fo, "%s", genbuf); + } + if (!hastime){ + now += 14*24*60*60; + fprintf(fo, "�s�p�����ɶ�: (%ld)%s", now, ctime(&now)); + now -= 14*24*60*60; + } + + fprintf(fo, "%s", genbuf); + + do{ + if (!getdata(18, 0, "�аݱz (Y)��� (N)�Ϲ� �o��ij�D�G", opnion, 3, LCECHO)){ + flock(fd, LOCK_UN); + close(fd); + fclose(fo); + unlink(fpath); + return; + } + }while(opnion[0] != 'y' && opnion[0] != 'n'); + + if (!getdata(20, 0, "�аݱz�P�o��ij�D�����Y�γs�p�z�Ѭ���G", reason, 40, DOECHO)){ + flock(fd, LOCK_UN); + close(fd); + fclose(fo); + unlink(fpath); + return; + } + + i = 0; + + while(fo){ + i++; + j = 0; + do{ + if (read(fd, genbuf+j, 1)<=0){ + flock(fd, LOCK_UN); + close(fd); + fclose(fo); + unlink(fpath); + return; + } + j++; + }while(genbuf[j-1] !='\n'); + genbuf[j] = '\0'; + if (!strncmp("----------", genbuf, 10)) + break; + if (strncmp(genbuf+4, cuser.userid, len)) + fprintf(fo, "%3d.%s", i, genbuf+4); + else + i--; + } + if (opnion[0] == 'y') + fprintf(fo, "%3d.%-15s%-34s �ӷ�:%s\n", i, cuser.userid, reason,cuser.lasthost); + i = 0; + fprintf(fo, "%s", genbuf); + while(fo){ + i++; + j = 0; + do{ + if (!read(fd, genbuf+j, 1)) + break; + j++; + }while(genbuf[j-1] !='\n'); + genbuf[j] = '\0'; + if (j <= 3) + break; + if (strncmp(genbuf+4, cuser.userid, len)) + fprintf(fo, "%3d.%s", i, genbuf+4); + else + i--; + } + if (opnion[0] == 'n') + fprintf(fo, "%3d.%-15s%-34s �ӷ�:%s\n", i, cuser.userid, reason,cuser.lasthost); + flock(fd, LOCK_UN); + close(fd); + fclose(fo); + unlink(oldfpath); + rename(fpath, oldfpath); +} + +int do_voteboard() { + fileheader_t votefile; + char topic[100]; + char title[80]; + char genbuf[1024]; + char fpath[80]; + FILE* fp; + int temp, i; + time_t now = time(NULL); + + clear(); + if(!(currmode & MODE_POST)) { + move(5, 10); + outs("�藍�_�A�z�ثe�L�k�b���o���峹�I"); + pressanykey(); + return FULLUPDATE; + } + + move(0, 0); + clrtobot(); + prints("�z���b�ϥ� PTT ���s�p�t��\n"); + prints("���s�p�t�αN�߰ݱz�@�ǰ��D�A�Фp�ߦ^���~��}�l�s�p\n"); + prints("���N���X�s�p�ת̡A�N�Q�C�J���t�Τ����w��ϥΪ̳�\n"); + pressanykey(); + move(0, 0); + clrtobot(); + prints("(1)�ӽзs�� (2)�o���ª� (3)�s�p���D (4)�}�K���D\n"); + if (!strcmp(currboard, VOTEBOARD)) + prints("(5)�s�p�p�ժ� (6)�}�K�p�ժ� "); + if (!strcmp(currboard, VOTEBOARD) && HAS_PERM(PERM_SYSOP)) + prints("(7)��������"); + prints("(8)�ӽзs�s��"); + + do{ + getdata(3, 0, "�п�J�s�p���O�G", topic, 3, DOECHO); + temp = atoi(topic); + }while(temp <= 0 && temp >= 9); + + switch(temp){ + case 1: + do{ + if (!getdata(4, 0, "�п�J�ݪ��^��W�١G", topic, IDLEN+1, DOECHO)) + return FULLUPDATE; + else if (invalid_brdname(topic)) + outs("���O���T���ݪ��W��"); + else if (getbnum(topic) > 0) + outs("���W�٤w�g�s�b"); + else + break; + }while(temp > 0); + sprintf(title, "[�ӽзs��] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s","�ӽзs��", "�^��W��: ", topic, "����W��: "); + + if (!getdata(5, 0, "�п�J�ݪ�����W�١G", topic, 20, DOECHO)) + return FULLUPDATE; + strcat(genbuf, topic); + strcat(genbuf, "\n�ݪ����O: "); + if (!getdata(6, 0, "�п�J�ݪ����O�G", topic, 20, DOECHO)) + return FULLUPDATE; + strcat(genbuf, topic); + strcat(genbuf, "\n���D�W��: "); + getdata(7, 0, "�п�J���D�W��G", topic, IDLEN * 3 + 3, DOECHO); + strcat(genbuf, topic); + strcat(genbuf, "\n�ӽЭ�]: \n"); + outs("�п�J�ӽЭ�](�ܦh����)�A�n�M����g���M���|�֭��"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "�G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 2: + do{ + if (!getdata(4, 0, "�п�J�ݪ��^��W�١G", topic, IDLEN+1, DOECHO)) + return FULLUPDATE; + else if (getbnum(topic) <= 0) + outs("���W�٨ä��s�b"); + else + break; + }while(temp > 0); + sprintf(title, "[�o���ª�] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n","�o���ª�", "�^��W��: ", topic); + strcat(genbuf, "\n�o����]: \n"); + outs("�п�J�o����](�ܦh����)�A�n�M����g���M���|�֭��"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "�G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + + break; + case 3: + do{ + if (!getdata(4, 0, "�п�J�ݪ��^��W�١G", topic, IDLEN+1, DOECHO)) + return FULLUPDATE; + else if (getbnum(topic) <= 0) + outs("���W�٨ä��s�b"); + else + break; + }while(temp > 0); + sprintf(title, "[�s�p���D] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s%s","�s�p���D", "�^��W��: ", topic, "�ӽ� ID : ", cuser.userid); + strcat(genbuf, "\n�ӽЬF��: \n"); + outs("�п�J�ӽЬF��(�ܦh����)�A�n�M����g���M���|�֭��"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "�G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 4: + do{ + if (!getdata(4, 0, "�п�J�ݪ��^��W�١G", topic, IDLEN+1, DOECHO)) + return FULLUPDATE; + else if ((i = getbnum(topic)) <= 0) + outs("���W�٨ä��s�b"); + else + break; + }while(temp > 0); + sprintf(title, "[�}�K���D] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s","�}�K���D", "�^��W��: ", topic, "���D ID : "); + do{ + if (!getdata(6, 0, "�п�J���DID�G", topic, IDLEN + 1, DOECHO)) + return FULLUPDATE; + else if (!userid_is_BM(topic, bcache[i-1].BM)) + outs("���O�Ӫ������D"); + else + break; + }while(temp > 0); + strcat(genbuf, topic); + strcat(genbuf, "\n�}�K��]: \n"); + outs("�п�J�}�K��](�ܦh����)�A�n�M����g���M���|�֭��"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "�G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 5: + if (!getdata(4, 0, "�п�J�p�դ��^��W�١G", topic, 30, DOECHO)) + return FULLUPDATE; + sprintf(title, "[�s�p�p�ժ�] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s%s","�s�p�p�ժ�", "�p�զW��: ", topic, "�ӽ� ID : ", cuser.userid); + strcat(genbuf, "\n�ӽЬF��: \n"); + outs("�п�J�ӽЬF��(�ܦh����)�A�n�M����g���M���|�֭��"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "�G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 6: + + if (!getdata(4, 0, "�п�J�p�դ��^��W�١G", topic, 30, DOECHO)) + return FULLUPDATE; + sprintf(title, "[�}�K�p�ժ�] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s","�}�K�p�ժ�", "�p�զW��: ", topic, "�p�ժ� ID : "); + if (!getdata(6, 0, "�п�J�p�ժ�ID�G", topic, IDLEN + 1, DOECHO)) + return FULLUPDATE; + strcat(genbuf, topic); + strcat(genbuf, "\n�}�K��]: \n"); + outs("�п�J�}�K��](�ܦh����)�A�n�M����g���M���|�֭��"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "�G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 7: + if (!HAS_PERM(PERM_SYSOP)) + return FULLUPDATE; + if (!getdata(4, 0, "�п�J����D�D�G", topic, 30, DOECHO)) + return FULLUPDATE; + sprintf(title, "%s %s", "[��������]", topic); + sprintf(genbuf, "%s\n\n%s%s\n","��������", "����D�D: ", topic); + strcat(genbuf, "\n�����]: \n"); + outs("�п�J�����](�ܦh����)�A�n�M����g���M���|�֭��"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "�G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + case 8: + if(!getdata(4, 0, "�п�J�s�դ��^��W�١G", topic, 30, DOECHO)) + return FULLUPDATE; + sprintf(title, "[�ӽзs�s��] %s", topic); + sprintf(genbuf, "%s\n\n%s%s\n%s%s","�ӽиs��", "�s�զW��: ", topic, "�ӽ� ID : ", cuser.userid); + strcat(genbuf, "\n�ӽЬF��: \n"); + outs("�п�J�ӽЬF��(�ܦh����)�A�n�M����g���M���|�֭��"); + for(i= 8;i<13;i++){ + if (!getdata(i, 0, "�G", topic, 60, DOECHO)) + break; + strcat(genbuf, topic); + strcat(genbuf, "\n"); + } + if (i==8) + return FULLUPDATE; + break; + default: + return FULLUPDATE; + } + strcat(genbuf, "�s�p�����ɶ�: "); + now += 14*24*60*60; + sprintf(topic, "(%ld)", now); + strcat(genbuf, topic); + strcat(genbuf, ctime(&now)); + 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", "�@��: ", cuser.userid, + "�ݪO: ", currboard, + "���D: ", title, + "�ɶ�: ", ctime(&now)); + fprintf(fp, "%s\n", genbuf); + fclose(fp); + strcpy(votefile.owner, cuser.userid); + strcpy(votefile.title, title); + votefile.savemode = 'S'; + 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 new file mode 100644 index 00000000..786add30 --- /dev/null +++ b/mbbsd/xyz.c @@ -0,0 +1,448 @@ +/* $Id: xyz.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <signal.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include "config.h" +#include "pttstruct.h" +#include "common.h" +#include "modes.h" +#include "proto.h" + +extern char *fn_note_ans; +extern int b_lines; /* Screen bottom line number: t_lines-1 */ +extern char *BBSName; +extern char fromhost[]; +extern userinfo_t *currutmp; +extern int curr_idle_timeout; +extern userec_t cuser; + +/* �U�زέp�ά�����T�C�� */ +/* Ptt90�~�פj���p�۬d�]�t�� */ +int x_90() { + extern char dict[21], database[41]; + strcpy(dict, "(90)����Ҹ�/�m�W/�Ǯ�/��t/����"); + strcpy(database, "etc/90"); + use_dict(); + return 0; +} + +/* Ptt89�~�פj���p�۬d�]�t�� */ +int x_89() { + extern char dict[21], database[41]; + strcpy(dict, "(89)����Ҹ�/�m�W/�Ǯ�/��t/����"); + strcpy(database, "etc/89"); + use_dict(); + return 0; +} +/* Ptt88�~�פj���p�۬d�]�t�� */ +int x_88() { + extern char dict[21], database[41]; + + strcpy(dict, "(88)����Ҹ�/�m�W/�Ǯ�/��t/����"); + strcpy(database, "etc/88"); + use_dict(); + return 0; +} +/* Ptt87�~�פj���p�۬d�]�t�� */ +int x_87() { + extern char dict[21], database[41]; + + strcpy(dict, "(87)����Ҹ�/�m�W/�Ǯ�/��t"); + strcpy(database, "etc/87"); + use_dict(); + return 0; +} + +/* Ptt86�~�פj���p�۬d�]�t�� */ +int x_86() { + extern char dict[21], database[41]; + + strcpy(dict, "(86)����Ҹ�/�m�W/�Ǯ�/��t"); + strcpy(database, "etc/86"); + use_dict(); + return 0; +} + +int x_boardman() { + more("etc/topboardman", YEA); + return 0; +} + +int x_user100() { + more("etc/topusr100", YEA); + return 0; +} + +int x_history() { + more("etc/history", YEA); + return 0; +} + +#ifdef HAVE_X_BOARDS +static int x_boards() { + more("etc/topboard.tmp", YEA); + return 0; +} +#endif + +int x_birth() { + more("etc/birth.today", YEA); + return 0; +} + +int x_weather() { + more("etc/weather.tmp", YEA); + return 0; +} + +int x_stock() { + more("etc/stock.tmp", YEA); + return 0; +} + +int x_note() { + more(fn_note_ans, YEA); + return 0; +} + +int x_issue() { + more("etc/day", YEA); + return 0; +} + +int x_week() { + more("etc/week", YEA); + return 0; +} + +int x_today() { + more("etc/today", YEA); + return 0; +} + +int x_yesterday() { + more("etc/yesterday", YEA); + return 0; +} + +int x_login() { + more("etc/Welcome_login", YEA); + return 0; +} + +#ifdef HAVE_INFO +static int x_program() { + more("etc/version", YEA); + return 0; +} +#endif + +#ifdef HAVE_LICENSE +static int x_gpl() { + more("etc/GPL", YEA); + return 0; +} +#endif + +/* ���} BBS �� */ +int note() { + static char *fn_note_tmp = "note.tmp"; + static 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 { + time_t date; + char userid[IDLEN + 1]; + char username[19]; + char buf[3][80]; + } notedata_t; + notedata_t myitem; + + if(cuser.money < 5) { + outmsg("\033[1;41m �u�r! �n�뤭�Ȥ~��d��...�S���C..\033[m"); + clrtoeol(); + refresh(); + 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], 78, + 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); + strncpy(myitem.username, cuser.username, 18); + myitem.username[18] = '\0'; + time(&(myitem.date)); + + /* begin load file */ + if((foo = fopen(".note", "a")) == NULL) + return 0; + + if((fp = fopen(fn_note_ans, "w")) == NULL) + return 0; + + if((fx = open(fn_note_tmp, O_WRONLY | O_CREAT, 0644)) <= 0) + 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("\033[1;31;44m��s�w�w�w�w�w�w�w�w�w�w�w�w�w�w�t" + "\033[37m�IJ��W���O\033[31m�u�w�w�w�w�w�w�w�w�w�w�w�w�w�w�s��" + "\033[m\n", fp); + collect = 1; + + while(total) { + sprintf(buf, "\033[1;31m�~�t\033[32m %s \033[37m(%s)", + myitem.userid, myitem.username); + len = strlen(buf); + + for(i = len ; i < 73; i++) + strcat(buf, " "); + sprintf(buf2, " \033[1;36m%.14s\033[31m �u��\033[m\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, "\033[1;31m�x\033[m%-74.74s\033[1;31m�x\033[m\n", + myitem.buf[i]); + if(collect) + fprintf(foo, "\033[1;31m�x\033[m%-74.74s\033[1;31m�x\033[m\n", + myitem.buf[i]); + } + fputs("\033[1;31m���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��\033[m\n",fp); + + if(collect) { + fputs("\033[1;31m���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��\033[m\n", foo); + fclose(foo); + collect = 0; + } + + write(fx, &myitem, sizeof(myitem)); + + if(--total) + read(fd, (char *) &myitem, sizeof(myitem)); + } + fputs("\033[1;31;44m��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��\033[m\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() { + 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); + } + } + } + } + + move(12, 0); + clrtobot(); + prints("%16s %-18s�v�d����\n\n", "�s��", "���� ID"); + + for(i = 0; i < j; i++) + prints("%15d. \033[1;%dm%-16s%s\033[0m\n", + i + 1, 31 + i % 7, sysoplist[i].userid, sysoplist[i].duty); + prints("%-14s0. \033[1;%dm���}\033[0m", "", 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) { + clear(); + do_send(sysoplist[i].userid, NULL); + } + } +} + +int m_sysop() { + setutmpmode(MSYSOP); + mail_sysop(); + return 0; +} + +int Goodbye() { + extern void movie(); + char genbuf[100]; + + getdata(b_lines - 1, 0, "�z�T�w�n���}�i " BBSNAME " �j��(Y/N)�H[N] ", + genbuf, 3, LCECHO); + + if(*genbuf != 'y') + return 0; + + movie(999); + if(cuser.userlevel) { + getdata(b_lines - 1, 0, + "(G)�H���ӳu (M)���گ��� (N)�IJ��W���y�����H[G] ", + genbuf, 3, LCECHO); + if(genbuf[0] == 'm') + mail_sysop(); + else if(genbuf[0] == 'n') + note(); + } + + clear(); + prints("\033[1;36m�˷R�� \033[33m%s(%s)\033[36m�A�O�ѤF�A�ץ��{\033[45;33m" + " %s \033[40;36m�I\n�H�U�O�z�b���������U���:\033[0m\n", + cuser.userid, cuser.username, BBSName); + user_display(&cuser, 0); + pressanykey(); + + more("etc/Logout",NA); + pressanykey(); + u_exit("EXIT "); + return QUIT; +} + +/* �䴩�~���{�� : tin�Bgopher�Bwww�Bbbsnet�Bgame�Bcsh */ +#define LOOKFIRST (0) +#define LOOKLAST (1) +#define QUOTEMODE (2) +#define MAXCOMSZ (1024) +#define MAXARGS (40) +#define MAXENVS (20) +#define BINDIR BBSHOME"/bin/" + +#define MAXPATHLEN 256 + +#ifdef HAVE_TIN +static int x_tin() { + clear(); + return exec_cmd(NEWS, YEA, "bin/tin.sh", "TIN"); +} +#endif + +#ifdef HAVE_GOPHER +static int x_gopher() { + clear(); + return exec_cmd(GOPHER, YEA, "bin/gopher.sh", "GOPHER"); +} +#endif + +#ifdef HAVE_WWW +static int x_www() { + return exec_cmd(WWW, NA, "bin/www.sh", "WWW"); +} +#endif + +#ifdef HAVE_IRC +static int x_irc() { + return exec_cmd(XMODE, NA, "bin/irc.sh", "IRC"); +} +#endif + +#ifdef HAVE_ARCHIE +static int x_archie() { + char buf[STRLEN], ans[4]; + char genbuf1[100], genbuf2[200]; + char *s; + + setutmpmode(ARCHIE); + clear(); + outs("\n�w����{�i\033[1;33;44m" BBSNAME "\033[m�j�ϥ� " + "\033[32mARCHIE\033[m �\\��\n"); + outs("\n���\\��N���z�C�X�b���� FTP ���s���z���M�䪺�ɮ�.\n"); + outs("\n�п�J���j�M���r��, �Ϊ����� <ENTER> �����C\n"); + outs("\n coder by Harimau\n"); + outs(" modified by Leeym\n"); + getdata(13,0,"�j�M�r��G",buf,20,DOECHO,0); + if(buf[0]=='\0') { + prints("\n�����j�M.....\n"); + pressanykey(); + return; + } + + for(s = buf; *s != '\0'; s++) { + if(isspace(*s)) { + prints("\n�@���u��j�M�@�Ӧr���, ����ӳg�߳�!!"); + pressanykey(); + return; + } + } + bbssetenv("ARCHIESTRING", buf); + exec_cmd(ARCHIE, YEA, "bin/archie.sh", ARCHIE); + log_usies("ARCHIE", ""); + strcpy(genbuf1, buf); + sprintf(buf, BBSHOME "/tmp/archie.%s", cuser.userid); + if(dashf(buf)) { + getdata(0, 0, "�n�N���G�H�^�H�c��(Y/N)�H[N]", ans, 3, DOECHO,0); + if(*ans == 'y') { + fileheader_t mhdr; + char title[128], buf1[80]; + FILE* fp; + + sethomepath(buf1, cuser.userid); + stampfile(buf1, &mhdr); + strcpy(mhdr.owner, cuser.userid); + sprintf(genbuf2, "Archie �j�M�ɮ�: %s ���G", genbuf1); + strcpy(mhdr.title, genbuf2); + mhdr.savemode = 0; + mhdr.filemode = 0; + sethomedir(title, cuser.userid); + append_record(title, &mhdr, sizeof(mhdr)); + Link(buf, buf1); + } + more( buf, YEA); + unlink (buf); + } +} +#endif /* HAVE_ARCHIE */ -- cgit v1.2.3