/*-------------------------------------------------------*/
/* io.c ( NTHU CS MapleBBS Ver 2.36 ) */
/*-------------------------------------------------------*/
/* target : basic console/screen/keyboard I/O routines */
/* create : 95/02/28 */
/* update : 95/12/15 */
/*-------------------------------------------------------*/
#include "bbs.h"
#ifdef AIX
#include <sys/select.h>
#endif
#ifdef Linux
#define OBUFSIZE (2048)
#define IBUFSIZE (128)
#else
#define OBUFSIZE (4096)
#define IBUFSIZE (256)
#endif
#define INPUT_ACTIVE 0
#define INPUT_IDLE 1
static char outbuf[OBUFSIZE];
static int obufsize = 0;
static char inbuf[IBUFSIZE];
static int ibufsize = 0;
static int icurrchar = 0;
static int i_mode = INPUT_ACTIVE;
extern int dumb_term;
/* ----------------------------------------------------- */
/* 定時顯示動態看板 */
/* ----------------------------------------------------- */
#ifdef HAVE_MOVIE
#define STAY_TIMEOUT (30*60)
extern void movie();
static char *Proverb[100];
static char Proverbtop=0;
void GetProverb()
{
char buf[256];
FILE *fp;
setuserfile(buf,fn_proverb);
if(fp=fopen(buf,"r"))
{
Proverbtop=0;
while(fgets(buf,200,fp) && Proverbtop <=99)
{
char *ch;
if(ch=strchr(buf,'\n')) *ch=0;
if(buf[0])
{
Proverb[Proverbtop]=(char *) malloc(strlen(buf) + 1);
strcpy(Proverb[Proverbtop],buf);
Proverbtop++;
}
}
fclose(fp);
}
if(!Proverbtop)
{
Proverb[0]=(char *) malloc(100);
strcpy(Proverb[0],"座右銘狀態為[自定型]要記得設座右銘的內容唷!!");
Proverbtop=1;
}
}
static void
hit_alarm_clock()
{
static int stay_time = 0;
static int idle_time = 0;
if (currutmp->pid != currpid)
{
setup_utmp(XMODE); /* 重新配置 shm */
}
if ((i_mode == INPUT_IDLE) && (!HAS_PERM(PERM_NOTIMEOUT)) && (!HAS_PERM(PERM_SYSOP))
&& currstat != MAILALL && !PERM_HIDE(currutmp))
{
idle_time += MOVIE_INT;
if (idle_time > IDLE_TIMEOUT)
{
clear();
fprintf(stderr, "超過閒置時間! 去約會啦? 扣錢踢出去囉 ………\n");
demoney(10); /* 扣十兩銀 */
abort_bbs();
}
}
else
{
idle_time = 0;
i_mode = INPUT_IDLE;
}
if (currstat && (currstat < CLASS || currstat == MAILALL))
movie(0);
alarm(MOVIE_INT);
stay_time += MOVIE_INT;
if (chkmail(0) && stay_time > 10 * 60 || stay_time > STAY_TIMEOUT)
{
/* 在這裡提示 user 休息一下 */
char *msg[10] = {"伸伸腰, 揉揉眼, 喝口茶....喘口氣...再繼續...!",
"一邊是友情 一邊是愛情 左右的故事為難著自己...",
"是否有人瞭解您內心的孤寂? 大家來talk talk吧.. ",
"左三圈,右三圈,脖子扭扭屁股扭扭 大家來作運動唷~",
"我灌..我灌..我灌灌灌! 灌到硬碟爆掉...",
"用‧功\‧唸‧書",
"書念完了沒啊....^.^",
"明天有沒有考試啊...念書重要唷...!",
"學海本無止境,唯有篤學沉靜之士始能入得其深.",
"‧書在心中氣自皇‧讀書去‧"};
/*
woju
*/
time_t now = time(0);
char buf[100];
int i = rand() % 5 , j ;
if(!chkmail(0)) /* Ptt */
{
switch (cuser.proverb)
{
case 2: /* 自定型 */
if(!Proverbtop) GetProverb();
j = rand() % Proverbtop;
msg[i+5] = Proverb[j];
case 0: /* 用功型 */
i+=5;
case 1: /* 安逸型 */
sprintf(currmsg, "[%s] %s",
Cdate(&now), msg[i]);
kill(currpid, SIGUSR2);
case 3:
break;
}
}
else
{
sprintf(currmsg, "[%s] 信箱裏還有沒看過的信唷",
Cdate(&now));
kill(currpid, SIGUSR2);
}
stay_time = 0;
}
if (idle_time > IDLE_TIMEOUT - 60)
{
sprintf(currmsg, "警告:您已閒置過久,"
"若無回應,系統即將切離!! 並課十兩罰金!!");
kill(currpid, SIGUSR2);
}
}
void
init_alarm()
{
alarm(0);
signal(SIGALRM, hit_alarm_clock);
alarm(MOVIE_INT);
}
#else /* HAVE_MOVIE */
static void
hit_alarm_clock()
{
if (HAS_PERM(PERM_NOTIMEOUT) || PERM_HIDE(currutmp) || currstat == MAILALL)
return;
if (i_mode == INPUT_IDLE)
{
clear();
fprintf(stderr, "超過閒置時間!Booting...\n");
kill(currpid, SIGHUP);
}
i_mode = INPUT_IDLE;
alarm(IDLE_TIMEOUT);
}
void
init_alarm()
{
signal(SIGALRM, hit_alarm_clock);
alarm(IDLE_TIMEOUT);
}
#endif /* HAVE_MOVIE */
/* ----------------------------------------------------- */
/* output routines */
/* ----------------------------------------------------- */
void
oflush()
{
if (obufsize)
{
write(1, outbuf, obufsize);
obufsize = 0;
}
}
void
output(s, len)
char *s;
{
/* Invalid if len >= OBUFSIZE */
if (obufsize + len > OBUFSIZE)
{
write(1, outbuf, obufsize);
obufsize = 0;
}
memcpy(outbuf + obufsize, s, len);
obufsize += len;
}
void
ochar(c)
{
if (obufsize > OBUFSIZE - 1)
{
write(1, outbuf, obufsize);
obufsize = 0;
}
outbuf[obufsize++] = c;
}
/* ----------------------------------------------------- */
/* input routines */
/* ----------------------------------------------------- */
static int i_newfd = 0;
static struct timeval i_to, *i_top = NULL;
static int (*flushf) () = NULL;
void
add_io(fd, timeout)
int fd;
int timeout;
{
i_newfd = fd;
if (timeout)
{
i_to.tv_sec = timeout;
i_to.tv_usec = 0;
i_top = &i_to;
}
else
i_top = NULL;
}
void
add_flush(flushfunc)
int (*flushfunc) ();
{
flushf = flushfunc;
}
int
num_in_buf()
{
return icurrchar - ibufsize;
}
int
igetch()
{
int ch;
for (;;)
{
if (ibufsize == icurrchar)
{
fd_set readfds;
struct timeval to;
to.tv_sec = to.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
if (i_newfd)
FD_SET(i_newfd, &readfds);
if ((ch = select(FD_SETSIZE, &readfds, NULL, NULL, &to)) <= 0)
{
if (flushf)
(*flushf) ();
if (dumb_term)
oflush();
else
refresh();
FD_ZERO(&readfds);
FD_SET(0, &readfds);
if (i_newfd)
FD_SET(i_newfd, &readfds);
while ((ch = select(FD_SETSIZE, &readfds, NULL, NULL, i_top)) < 0)
{
if (errno == EINTR)
continue;
else
{
perror("select");
return -1;
}
}
if (ch == 0)
return I_TIMEOUT;
}
if (i_newfd && FD_ISSET(i_newfd, &readfds))
return I_OTHERDATA;
while ((ibufsize = read(0, inbuf, IBUFSIZE)) <= 0)
{
if (ibufsize == 0)
longjmp(byebye, -1);
if (ibufsize < 0 && errno != EINTR)
longjmp(byebye, -1);
}
icurrchar = 0;
}
i_mode = INPUT_ACTIVE;
ch = inbuf[icurrchar++];
if (ch != Ctrl('L'))
return (ch);
redoscr();
}
}
char* phone_char(char c)
{
switch (c) {
case '1':
return "ㄅ";
case 'q':
return "ㄆ";
case 'a':
return "ㄇ";
case 'z':
return "ㄈ";
case '2':
return "ㄉ";
case 'w':
return "ㄊ";
case 's':
return "ㄋ";
case 'x':
return "ㄌ";
case 'e':
return "ㄍ";
case 'd':
return "ㄎ";
case 'c':
return "ㄏ";
case 'r':
return "ㄐ";
case 'f':
return "ㄑ";
case 'v':
return "ㄒ";
case '5':
return "ㄓ";
case 't':
return "ㄔ";
case 'g':
return "ㄕ";
case 'b':
return "ㄖ";
case 'y':
return "ㄗ";
case 'h':
return "ㄘ";
case 'n':
return "ㄙ";
case 'u':
return "ㄧ";
case 'j':
return "ㄨ";
case 'm':
return "ㄩ";
case '8':
return "ㄚ";
break;
case 'i':
return "ㄛ";
case 'k':
return "ㄜ";
case ',':
return "ㄝ";
case '9':
return "ㄞ";
case 'o':
return "ㄟ";
case 'l':
return "ㄠ";
case '.':
return "ㄡ";
case '0':
return "ㄢ";
case 'p':
return "ㄣ";
case ';':
return "ㄤ";
case '/':
return "ㄥ";
case '-':
return "ㄦ";
case '6':
return "ˊ";
case '3':
return "ˇ";
case '4':
return "ˋ";
case '7':
return "˙";
}
return 0;
}
char watermode; /* Ptt 水球回顧用的參數 */
extern char no_oldmsg,oldmsg_count;
int
oldgetdata(line, col, prompt, buf, len, echo)
int line, col;
char *prompt, *buf;
int len, echo;
{
register int ch;
int clen;
int x=col, y=line;
extern unsigned char scr_cols;
#define MAXLASTCMD 12
static char lastcmd[MAXLASTCMD][80];
watermode=0;
if (prompt)
{
move(line, col);
clrtoeol();
outs(prompt);
x += strip_ansi(NULL,prompt,0);
}
if (dumb_term || !echo)
{
len--;
clen = 0;
while ((ch = igetch()) != '\r')
{
if (ch == '\n')
break;
if (ch == '\177' || ch == Ctrl('H'))
{
if (!clen)
{
bell();
continue;
}
clen--;
if (echo)
{
ochar(Ctrl('H'));
ochar(' ');
ochar(Ctrl('H'));
}
continue;
}
#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;
int phone_mode = 0;
char* pstr;
/* getyx(&y, &x);*/
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')
{
/*
Ptt
*/
switch (ch) {
case Ctrl('R'): /* Ptt for water ball */
if (!currutmp->mode && (currutmp->chatid[0] == 2 ||
currutmp->chatid[0] == 3) && oldmsg_count)
{
/*
extern screenline* big_picture;
screenline* screen0 = calloc(t_lines, sizeof(screenline));
memcpy(screen0, big_picture, t_lines * sizeof(screenline));
*/
watermode=1;
t_display_new();
/*
memcpy(big_picture, screen0, t_lines * sizeof(screenline));
free(screen0);
redoscr();
*/
continue;
}
else continue;
case KEY_DOWN:
case Ctrl('N'):
buf[clen] = '\0'; /* Ptt */
strncpy(lastcmd[cmdpos],buf,79);
cmdpos += MAXLASTCMD - 2;
case Ctrl('P'):
case KEY_UP:
{
int i;
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);
}
continue;
case KEY_TAB:
if(watermode)
{
watermode = (watermode + oldmsg_count)% oldmsg_count + 1;
t_display_new();
}
continue;
case KEY_LEFT:
if (currchar)
--currchar;
continue;
case KEY_RIGHT:
if (buf[currchar])
++currchar;
continue;
case KEY_ESC:
if (KEY_ESC_arg == 'p')
phone_mode ^= 1;
else if (KEY_ESC_arg == 'c')
capture_screen();
else if (KEY_ESC_arg == 'n') {
extern screenline* big_picture;
screenline* screen0 = calloc(t_lines, sizeof(screenline));
memcpy(screen0, big_picture, t_lines * sizeof(screenline));
edit_note();
memcpy(big_picture, screen0, t_lines * sizeof(screenline));
free(screen0);
redoscr();
}
if (ch == 'U' && currstat != IDLE &&
!(currutmp->mode == 0 &&
(currutmp->chatid[0] == 2 || currutmp->chatid[0] == 3))) {
extern screenline* big_picture;
screenline* screen0 = calloc(t_lines, sizeof(screenline));
memcpy(screen0, big_picture, t_lines * sizeof(screenline));
t_users();
memcpy(big_picture, screen0, t_lines * sizeof(screenline));
free(screen0);
redoscr();
}
continue;
}
if (ch == '\n' || ch == '\r')
break;
/*
woju
*/
if (currutmp->msgs[0].last_pid && ch == Ctrl('R') &&
!(currutmp->mode == 0 &&
(currutmp->chatid[0] == 2 || currutmp->chatid[0] == 3))) {
extern screenline* big_picture;
screenline* screen0 = calloc(t_lines, sizeof(screenline));
memcpy(screen0, big_picture, t_lines * sizeof(screenline));
show_last_call_in();
my_write(currutmp->msgs[0].last_pid, "水球丟回去:");
memcpy(big_picture, screen0, t_lines * sizeof(screenline));
free(screen0);
redoscr();
continue;
}
if (ch == Ctrl('I') && currstat != IDLE &&
!(currutmp->mode == 0 &&
(currutmp->chatid[0] == 2 || currutmp->chatid[0] == 3))) {
extern screenline* big_picture;
screenline* screen0 = calloc(t_lines, sizeof(screenline));
memcpy(screen0, big_picture, t_lines * sizeof(screenline));
t_idle();
memcpy(big_picture, screen0, t_lines * sizeof(screenline));
free(screen0);
redoscr();
continue;
}
if (ch == '\177' || ch == Ctrl('H'))
{
if (currchar) {
int i;
currchar--;
clen--;
for (i = currchar; i <= clen; i++)
buf[i] = buf[i + 1];
move(y, x + clen);
outc(' ');
move(y, x);
edit_outs(buf);
}
/*
if (clen)
{
clen--;
move(y, x + clen);
outc(' ');
move(y, x + clen);
}
*/
continue;
}
if (ch == Ctrl('Y')) {
int i;
buf[0] = 0;
currchar = 0;
move(y, x); /* clrtoeof */
for (i = 0; i < clen; i++)
outc(' ');
clen = 0;
continue;
}
if (ch == Ctrl('D')) {
if (buf[currchar]) {
int i;
clen--;
for (i = currchar; i <= clen; i++)
buf[i] = buf[i + 1];
move(y, x + clen);
outc(' ');
move(y, x);
edit_outs(buf);
}
continue;
}
if (ch == Ctrl('K')) {
int i;
buf[currchar] = 0;
move(y, x + currchar);
for (i = currchar; i < clen; i++)
outc(' ');
clen = currchar;
continue;
}
if (ch == Ctrl('A')) {
currchar = 0;
continue;
}
if (ch == Ctrl('E')) {
currchar = clen;
continue;
}
if (!(phone_mode && (pstr = phone_char(ch)) || isprint2(ch) || ch == Ctrl('U') && HAS_PERM(PERM_SYSOP)))
{
continue;
}
if (clen + (phone_mode && pstr) >= len || x + clen >= scr_cols)
{
continue;
}
/*
woju
*/
if (buf[currchar]) { /* insert */
int i;
for (i = currchar; buf[i] && i + (phone_mode && pstr) < len && i + (phone_mode && pstr) < 80; i++)
;
buf[i + 1 + (phone_mode && pstr)] = 0;
for (; i > currchar; i--)
buf[i + (phone_mode && pstr)] = buf[i - 1];
}
else /* append */
buf[currchar + 1 + (phone_mode && pstr)] = '\0';
if (ch == Ctrl('U'))
ch = KEY_ESC;
if (phone_mode && pstr) {
buf[currchar] = pstr[0];
buf[currchar + 1] = pstr[1];
}
else
buf[currchar] = ch;
move(y, x + currchar);
edit_outs(buf + currchar);
currchar++;
currchar += phone_mode && pstr;
clen++;
clen += phone_mode && pstr;
}
buf[clen] = '\0';
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;
return clen;
}
/* Ptt */
int
getdata_buf(line, col, prompt, buf, len, echo)
{
return oldgetdata(line, col, prompt, buf, len, echo);
}
int
getdata_str(line, col, prompt, buf, len, echo,defaultstr)
int line, col;
char *prompt, *buf;
int len, echo;
char *defaultstr;
{
strncpy(buf,defaultstr,len);
buf[len]=0;
return oldgetdata(line, col, prompt, buf, len, echo);
}
int
getdata(line, col, prompt, buf, len, echo)
int line, col;
char *prompt, *buf;
int len, echo;
{
buf[0]=0;
return oldgetdata(line, col, prompt, buf, len, echo);
}
/*
woju
*/
#define TRAP_ESC
#ifdef TRAP_ESC
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;
}
}
#else /* TRAP_ESC */
int
igetkey(void)
{
int mode;
int ch, last;
mode = last = 0;
while (1)
{
ch = igetch();
if (ch == KEY_ESC)
mode = 1;
else if (mode == 0) /* Normal Key */
return ch;
else if (mode == 1)
{ /* Escape sequence */
if (ch == '[' || ch == 'O')
mode = 2;
else if (ch == '1' || ch == '4')
mode = 3;
else
return ch;
}
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;
}
}
#endif /* TRAP_ESC */