精華區beta SetupBBS 關於我們 聯絡資訊
/*-------------------------------------------------------*/ /* 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 */