diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2009-10-23 01:18:07 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2009-10-23 01:18:07 +0800 |
commit | 0d7dfd6176178888a3b35ba6b75d27b87f6366c8 (patch) | |
tree | 33da2e0c88436c012212ce666494bb7920c50ce0 | |
parent | b5010ec3480855cacd1853b978ff575bc5eb9553 (diff) | |
download | pttbbs-0d7dfd6176178888a3b35ba6b75d27b87f6366c8.tar pttbbs-0d7dfd6176178888a3b35ba6b75d27b87f6366c8.tar.gz pttbbs-0d7dfd6176178888a3b35ba6b75d27b87f6366c8.tar.bz2 pttbbs-0d7dfd6176178888a3b35ba6b75d27b87f6366c8.tar.lz pttbbs-0d7dfd6176178888a3b35ba6b75d27b87f6366c8.tar.xz pttbbs-0d7dfd6176178888a3b35ba6b75d27b87f6366c8.tar.zst pttbbs-0d7dfd6176178888a3b35ba6b75d27b87f6366c8.zip |
* retab and refine
git-svn-id: http://opensvn.csie.org/pttbbs/trunk@4961 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r-- | pttbbs/mbbsd/ccw.c | 1000 |
1 files changed, 506 insertions, 494 deletions
diff --git a/pttbbs/mbbsd/ccw.c b/pttbbs/mbbsd/ccw.c index 3ca2a0ff..78328611 100644 --- a/pttbbs/mbbsd/ccw.c +++ b/pttbbs/mbbsd/ccw.c @@ -29,53 +29,56 @@ // [footer] // -------------------------------------------------------------------------- +// TODO +// 1. �Τ@ talk/chat ������W�١H (eg, �{��=���/�ͤѫǡA maybe ���/��ѫ� ?) + #define CCW_MAX_INPUT_LEN (STRLEN) -#define CCW_INIT_LINE (2) -#define CCW_STOP_LINE (t_lines-3) +#define CCW_INIT_LINE (2) +#define CCW_STOP_LINE (t_lines-3) // input style -#define CCW_REMOTE (0) -#define CCW_LOCAL (1) -#define CCW_LOCAL_MSG (2) +#define CCW_REMOTE (0) +#define CCW_LOCAL (1) +#define CCW_LOCAL_MSG (2) /////////////////////////////////////////////////////////////////////////// // Data Structure typedef struct CCW_CTX { // session - int abort; // indicate session complete - void *arg; // private argument + int abort; // indicate session complete + void *arg; // private argument // display - int line; // position of next line to append data + int line; // position of next line to append data int reset_scr; // need to redraw everything char *sep_msg; // quick help message on separators // input (vget) - int abort_vget; // temporary abort from input - const int MAX_INPUT_LEN; // max vget length, decided at init + int abort_vget; // temporary abort from input + const int MAX_INPUT_LEN; // max vget length, decided at init // logging - FILE *log; // log file handle + FILE *log; // log file handle char *log_fpath;// path of log file // network and remote int local_echo;// should we echo local input? - int fd; // remote connection + int fd; // remote connection char *remote_id;// remote user id char *local_id; // local user id // layout renderers - void (*header) (struct CCW_CTX *); - void (*prompt) (struct CCW_CTX *); - void (*footer) (struct CCW_CTX *); + void (*header) (struct CCW_CTX *); + void (*prompt) (struct CCW_CTX *); + void (*footer) (struct CCW_CTX *); void (*separators) (struct CCW_CTX *); // render header and footer separate lines // content processors - int (*peek_key) (struct CCW_CTX *, int key); - int (*peek_cmd) (struct CCW_CTX *, const char *buf, int local); - void (*print_line) (struct CCW_CTX *, const char *buf, int local); // print on screen + int (*peek_key) (struct CCW_CTX *, int key); + int (*peek_cmd) (struct CCW_CTX *, const char *buf, int local); + void (*print_line) (struct CCW_CTX *, const char *buf, int local); // print on screen void (*log_line) (struct CCW_CTX *, const char *buf, int local); // log to file - void (*post_input) (struct CCW_CTX *, const char *buf, int local); // after valid input + void (*post_input) (struct CCW_CTX *, const char *buf, int local); // after valid input } CCW_CTX; /////////////////////////////////////////////////////////////////////////// @@ -94,8 +97,8 @@ ccw_header(CCW_CTX *ctx) if (ctx->header) { - ctx->header(ctx); - return; + ctx->header(ctx); + return; } outs("Common Chat Window"); @@ -110,8 +113,8 @@ ccw_footer(CCW_CTX *ctx) if (ctx->footer) { - ctx->footer(ctx); - return; + ctx->footer(ctx); + return; } vs_footer(" CCW ", " (/b) ���} "); @@ -124,8 +127,8 @@ ccw_separators(CCW_CTX *ctx) if (ctx->separators) { - ctx->separators(ctx); - return; + ctx->separators(ctx); + return; } move(CCW_INIT_LINE-1, 0); @@ -148,8 +151,8 @@ ccw_prompt(CCW_CTX *ctx) if (ctx->prompt) { - ctx->prompt(ctx); - return; + ctx->prompt(ctx); + return; } prints("%s: ", ctx->local_id); @@ -159,13 +162,13 @@ static int ccw_peek_cmd(struct CCW_CTX *ctx, const char *buf, int local) { if (ctx->peek_cmd) - return ctx->peek_cmd(ctx, buf, local); + return ctx->peek_cmd(ctx, buf, local); // sample command: /b if (strcasecmp(buf, "/b") == 0) { - ctx->abort = 1; - return 1; + ctx->abort = 1; + return 1; } return 0; } @@ -176,19 +179,19 @@ ccw_print_line (struct CCW_CTX *ctx, const char *buf, int local) ccw_prepare_line(ctx); if (ctx->print_line) { - ctx->print_line(ctx, buf, local); - return; + ctx->print_line(ctx, buf, local); + return; } if (local <= CCW_LOCAL) // local or remote, but not message { - if (local) { - outs(ctx->local_id); - } else { - outs(ANSI_COLOR(1)); - outs(ctx->remote_id); - } - outs(": "); + if (local) { + outs(ctx->local_id); + } else { + outs(ANSI_COLOR(1)); + outs(ctx->remote_id); + } + outs(": "); } outs(buf); @@ -199,22 +202,22 @@ static void ccw_log_line (struct CCW_CTX *ctx, const char *buf, int local) { if (!ctx->log) - return; + return; if (ctx->log_line) { - ctx->log_line(ctx, buf, local); - return; + ctx->log_line(ctx, buf, local); + return; } if (local <= CCW_LOCAL) // local or remote, but not message { - fprintf(ctx->log, "%s%s: ", - local ? "" : ANSI_COLOR(1), - local ? ctx->local_id : ctx->remote_id); + fprintf(ctx->log, "%s%s: ", + local ? "" : ANSI_COLOR(1), + local ? ctx->local_id : ctx->remote_id); } fprintf(ctx->log, "%s%s\n", - buf, local ? "" : ANSI_RESET); + buf, local ? "" : ANSI_RESET); } // CCW utilities @@ -240,15 +243,15 @@ ccw_prepare_line(CCW_CTX *ctx) move(ctx->line, 0); if ( ctx->line+1 < CCW_STOP_LINE) { - // simply append - ctx->line ++; + // simply append + ctx->line ++; } else { - // scroll screen buffer - region_scroll_up(CCW_INIT_LINE, CCW_STOP_LINE - CCW_INIT_LINE); - move(ctx->line-1, 0); - // TODO after resize, we may need to scroll more than once. + // scroll screen buffer + region_scroll_up(CCW_INIT_LINE, CCW_STOP_LINE - CCW_INIT_LINE); + move(ctx->line-1, 0); + // TODO after resize, we may need to scroll more than once. } clrtoeol(); } @@ -261,7 +264,7 @@ ccw_partial_match(const char *buf, const char *cmd) assert(*cmd); if (!szbuf) - return 0; + return 0; return strncasecmp(buf, cmd, szbuf) == 0; } @@ -273,13 +276,13 @@ ccw_add_line (struct CCW_CTX *ctx, const char *buf, int local) // only print/log local when local_echo is enabled. if (local != CCW_LOCAL || ctx->local_echo) { - ccw_print_line(ctx, buf, local); - if (ctx->log) - ccw_log_line(ctx, buf, local); + ccw_print_line(ctx, buf, local); + if (ctx->log) + ccw_log_line(ctx, buf, local); } if (ctx->post_input) - ctx->post_input(ctx, buf, local); + ctx->post_input(ctx, buf, local); } // VGET callback adaptors @@ -290,9 +293,9 @@ ccw_vgetcb_peek(int key, VGET_RUNTIME *prt GCC_UNUSED, void *instance) CCW_CTX *ctx = (CCW_CTX*) instance; assert(ctx); if (ctx->peek_key && - ctx->peek_key(ctx, key)) + ctx->peek_key(ctx, key)) { - return (ctx->abort_vget || ctx->abort) ? VGETCB_ABORT : VGETCB_NEXT; + return (ctx->abort_vget || ctx->abort) ? VGETCB_ABORT : VGETCB_NEXT; } return VGETCB_NONE; @@ -308,52 +311,52 @@ ccw_process(CCW_CTX *ctx) VGET_CALLBACKS vgetcb = { ccw_vgetcb_peek }; assert( ctx->MAX_INPUT_LEN > 2 && - ctx->MAX_INPUT_LEN <= CCW_MAX_INPUT_LEN); + ctx->MAX_INPUT_LEN <= CCW_MAX_INPUT_LEN); ccw_reset_scr(ctx); #ifdef DEBUG ccw_print_line(ctx, ANSI_COLOR(1;30) - "�� Powered by piaip's Common Chat Window" ANSI_RESET, - CCW_LOCAL_MSG); + "�� Powered by piaip's Common Chat Window" ANSI_RESET, + CCW_LOCAL_MSG); #endif while (!ctx->abort) { - // reset screen or print prompts (may be destroyed by short message) - if (ctx->reset_scr) - ccw_reset_scr(ctx); - else { - ccw_footer(ctx); - ccw_prompt(ctx); - // reset again if prompt request to redraw. - if (ctx->reset_scr) - ccw_reset_scr(ctx); - } - - // get input - ctx->abort_vget = 0; - vgetstring(inbuf, ctx->MAX_INPUT_LEN, VGET_TRANSPARENT, "", - &vgetcb, ctx); - - // quick check for end flag or exit command. - if (ctx->abort) - break; - - // quick continue for empty input - trim(inbuf); - if (!*inbuf) - continue; - - // process commands - if (ccw_peek_cmd(ctx, inbuf, CCW_LOCAL)) - continue; - - // accept this data - ccw_add_line(ctx, inbuf, CCW_LOCAL); + // reset screen or print prompts (may be destroyed by short message) + if (ctx->reset_scr) + ccw_reset_scr(ctx); + else { + ccw_footer(ctx); + ccw_prompt(ctx); + // reset again if prompt request to redraw. + if (ctx->reset_scr) + ccw_reset_scr(ctx); + } + + // get input + ctx->abort_vget = 0; + vgetstring(inbuf, ctx->MAX_INPUT_LEN, VGET_TRANSPARENT, "", + &vgetcb, ctx); + + // quick check for end flag or exit command. + if (ctx->abort) + break; + + // quick continue for empty input + trim(inbuf); + if (!*inbuf) + continue; + + // process commands + if (ccw_peek_cmd(ctx, inbuf, CCW_LOCAL)) + continue; + + // accept this data + ccw_add_line(ctx, inbuf, CCW_LOCAL); } if (ctx->log) - fflush(ctx->log); + fflush(ctx->log); return 0; } @@ -368,7 +371,7 @@ ccw_talkchat_close_log(CCW_CTX *ctx, int force_decide, int is_chat) const char *fpath = ctx->log_fpath; if (!ctx->log) - return 0; + return 0; assert(*fpath); // flush @@ -379,40 +382,40 @@ ccw_talkchat_close_log(CCW_CTX *ctx, int force_decide, int is_chat) // prompt user to decide how to deal with the log while (1) { - char c; - getdata(b_lines - 1, 0, - force_decide ? "�M��(C) ���ܳƧѿ�(M)? [c/m]: " : - "�M��(C) ���ܳƧѿ�(M)? [C/m]", - ans, sizeof(ans), LCECHO); - - // decide default answer - c = *ans; - if (c != 'c' && c != 'm') - { - if (!force_decide) - c = 'c'; - } - - if (c == 'c') - break; - if (c == 'm') - { - char subj[STRLEN]; - if (is_chat) - snprintf(subj, sizeof(subj), "�|ij�O��"); - else - snprintf(subj, sizeof(subj), "��ܰO�� (%s)", ctx->remote_id); - - if (mail_log2id(cuser.userid, subj, fpath, "[��.��.��]", 0, 1) < 0) - vmsg("���~: �Ƨѿ��x�s���ѡC"); - break; - } - - // force user to input correct answer... - move(b_lines-2, 0); clrtobot(); - prints(ANSI_COLOR(0;1;3%d) "�Х��T��J c �� m �����O�C" ANSI_RESET, - (int)((now % 7)+1)); - if (c == 0) outs("���קK�~���ҥH�u�� ENTER �O���檺�C"); + char c; + getdata(b_lines - 1, 0, + force_decide ? "�M��(C) ���ܳƧѿ�(M)? [c/m]: " : + "�M��(C) ���ܳƧѿ�(M)? [C/m]", + ans, sizeof(ans), LCECHO); + + // decide default answer + c = *ans; + if (c != 'c' && c != 'm') + { + if (!force_decide) + c = 'c'; + } + + if (c == 'c') + break; + if (c == 'm') + { + char subj[STRLEN]; + if (is_chat) + snprintf(subj, sizeof(subj), "�|ij�O��"); + else + snprintf(subj, sizeof(subj), "��ܰO�� (%s)", ctx->remote_id); + + if (mail_log2id(cuser.userid, subj, fpath, "[��.��.��]", 0, 1) < 0) + vmsg("���~: �Ƨѿ��x�s���ѡC"); + break; + } + + // force user to input correct answer... + move(b_lines-2, 0); clrtobot(); + prints(ANSI_COLOR(0;1;3%d) "�Х��T��J c �� m �����O�C" ANSI_RESET, + (int)((now % 7)+1)); + if (c == 0) outs("���קK�~���ҥH�u�� ENTER �O���檺�C"); } unlink(fpath); return 1; @@ -437,9 +440,9 @@ ccw_talk_send(CCW_CTX *ctx, const char *msg) if (len < 1) return 0; if (towrite(ctx->fd, &len, 1) != 1) - return -1; + return -1; if (towrite(ctx->fd, msg, len)!= len) - return -1; + return -1; return len; } @@ -449,9 +452,9 @@ ccw_talk_recv(CCW_CTX *ctx, char *buf, size_t szbuf) char len = 0; buf[0] = 0; if (toread(ctx->fd, &len, 1) != 1) - return -1; + return -1; if (toread(ctx->fd, buf, len)!= len) - return -1; + return -1; assert(len >= 0 && len < szbuf); buf[(size_t)len] = 0; return len; @@ -461,53 +464,53 @@ static ssize_t ccw_talk_send_bye(CCW_CTX *ctx) { return ccw_talk_send(ctx, - CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_BYE); + CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_BYE); } static void ccw_talk_header(CCW_CTX *ctx) { prints(ANSI_COLOR(1;37;46) " �i��ѡj " - ANSI_COLOR(45) " %-*s" ANSI_RESET "\n", - t_columns - 12, ctx->remote_id); + ANSI_COLOR(45) " %-*s" ANSI_RESET "\n", + t_columns - 12, ctx->remote_id); } static void ccw_talk_footer(CCW_CTX *ctx) { vs_footer(" �i��ѡj ", " ( " - CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_BYE " )������� ( " - CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_CLEAR " )�M���e��" - "\t(Ctrl-C)���} "); + CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_BYE " )������� ( " + CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_CLEAR " )�M���e��" + "\t(Ctrl-C)���} "); } static int ccw_talk_peek_cmd(CCW_CTX *ctx, const char *buf, int local) { if (buf[0] != CCW_TALK_CMD_PREFIX) - return 0; + return 0; buf++; // process commands if (ccw_partial_match(buf, CCW_TALK_CMD_HELP)) { - ccw_print_line(ctx, "[����]: �i��J " - CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_CLEAR " �M���e���� " - CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_BYE " ���}�C", - CCW_LOCAL_MSG); - return 1; + ccw_print_line(ctx, "[����]: �i��J " + CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_CLEAR " �M���e���� " + CCW_TALK_CMD_PREFIX_STR CCW_TALK_CMD_BYE " ���}�C", + CCW_LOCAL_MSG); + return 1; } if (ccw_partial_match(buf, CCW_TALK_CMD_BYE)) { - ccw_talk_send_bye(ctx); // notify dest user if he's still online - ctx->abort = 1; - return 1; + ccw_talk_send_bye(ctx); // notify dest user if he's still online + ctx->abort = 1; + return 1; } if (ccw_partial_match(buf, CCW_TALK_CMD_CLEAR) || - ccw_partial_match(buf, CCW_TALK_CMD_CLS)) + ccw_partial_match(buf, CCW_TALK_CMD_CLS)) { - ctx->reset_scr = YEA; - return 1; + ctx->reset_scr = YEA; + return 1; } return 0; } @@ -516,7 +519,7 @@ static void ccw_talk_post_input(CCW_CTX *ctx, const char *buf, int local) { if (local != CCW_LOCAL) - return; + return; // send message to server if possible. ctx->abort = (ccw_talk_send(ctx, buf) <= 0); @@ -526,42 +529,42 @@ static int ccw_talk_peek_key(CCW_CTX *ctx, int key) { switch (key) { - case I_OTHERDATA: // incoming - { - char buf[STRLEN]; - if (ccw_talk_recv(ctx, buf, sizeof(buf)) < 1) - { - ctx->abort = YEA; - return 1; - } - // process commands - if (strcasecmp(buf, CCW_TALK_CMD_BYE) == 0) - { - ctx->abort = YEA; - return 1; - } - // received something, let's print it. - ccw_add_line(ctx, buf, CCW_REMOTE); - return 1; - } - - case Ctrl('C'): - { - VREFSCR scr = vscr_save(); - add_io(0, 0); - - if (vans("�T�w�n�����Ѷ�? [y/N]: ") == 'y') - ctx->abort = YEA; - - add_io(ctx->fd, 0); - vscr_restore(scr); - - // ccw_footer(ctx); - } - // notify remote user - if (ctx->abort) - ccw_talk_send(ctx, CCW_TALK_CMD_BYE); - return 1; + case I_OTHERDATA: // incoming + { + char buf[STRLEN]; + if (ccw_talk_recv(ctx, buf, sizeof(buf)) < 1) + { + ctx->abort = YEA; + return 1; + } + // process commands + if (strcasecmp(buf, CCW_TALK_CMD_BYE) == 0) + { + ctx->abort = YEA; + return 1; + } + // received something, let's print it. + ccw_add_line(ctx, buf, CCW_REMOTE); + return 1; + } + + case Ctrl('C'): + { + VREFSCR scr = vscr_save(); + add_io(0, 0); + + if (vans("�T�w�n�����Ѷ�? [y/N]: ") == 'y') + ctx->abort = YEA; + + add_io(ctx->fd, 0); + vscr_restore(scr); + + // ccw_footer(ctx); + } + // notify remote user + if (ctx->abort) + ccw_talk_send(ctx, CCW_TALK_CMD_BYE); + return 1; } return 0; } @@ -573,23 +576,23 @@ ccw_talk(int fd, int destuid) char remote_id[IDLEN+1], local_id[IDLEN+1]; CCW_CTX ctx = { - .fd = fd, - .abort = NA, - - .log = NULL, - .log_fpath = fpath, - .local_echo = YEA, - .MAX_INPUT_LEN = STRLEN - IDLEN - 5, // 5 for ": " and more - .remote_id = remote_id, - .local_id = local_id, - .sep_msg = " /b ���} /c �M���e�� ", - - .header = ccw_talk_header, - .footer = ccw_talk_footer, - - .peek_key = ccw_talk_peek_key, - .peek_cmd = ccw_talk_peek_cmd, - .post_input = ccw_talk_post_input, + .fd = fd, + .abort = NA, + + .log = NULL, + .log_fpath = fpath, + .local_echo = YEA, + .MAX_INPUT_LEN = STRLEN - IDLEN - 5, // 5 for ": " and more + .remote_id = remote_id, + .local_id = local_id, + .sep_msg = " /b ���} /c �M���e�� ", + + .header = ccw_talk_header, + .footer = ccw_talk_footer, + + .peek_key = ccw_talk_peek_key, + .peek_cmd = ccw_talk_peek_cmd, + .post_input = ccw_talk_post_input, }; STATINC(STAT_DOTALK); @@ -608,14 +611,15 @@ ccw_talk(int fd, int destuid) assert(ctx.log); fprintf(ctx.log, "[%s] �P %s ���:\n", Cdatelite(&now), ctx.remote_id); - // entering event loop... + // main processor add_io(fd, 0); ccw_process(&ctx); - // clean network handle + // clean network resource add_io(0, 0); close(fd); + // close log file ccw_talkchat_close_log(&ctx, YEA, NA); return 0; @@ -624,16 +628,16 @@ ccw_talk(int fd, int destuid) ///////////////////////////////////////////////////////////////////////////// // Chat -#define CHAT_ID_LEN (8) -#define CHAT_ROOM_LEN (IDLEN) -#define CHAT_TOPIC_LEN (48) // must < t_columns-CHAT_ROOM_LEN +#define CHAT_ID_LEN (8) +#define CHAT_ROOM_LEN (IDLEN) +#define CHAT_TOPIC_LEN (48) // must < t_columns-CHAT_ROOM_LEN typedef struct ccw_chat_ext { // misc int newmail; - int old_rows, old_cols; // for terminal resize auto detection + int old_rows, old_cols; // for terminal resize auto detection // buffer - int bufstart; + int buf_remains; char buf[128]; // topic char topic[CHAT_TOPIC_LEN+1]; @@ -652,15 +656,15 @@ ccw_chat_check_newmail(CCW_CTX *ctx) ccw_chat_ext *ext = ccw_chat_get_ext(ctx); if (ISNEWMAIL(currutmp)) { - if (!ext->newmail) - { - // no need to log this...? - ccw_print_line(ctx, "�� �z����Ū���s�H��C", CCW_LOCAL_MSG); - ext->newmail = 1; - } + if (!ext->newmail) + { + // no need to log this...? + ccw_print_line(ctx, "�� �z����Ū���s�H��C", CCW_LOCAL_MSG); + ext->newmail = 1; + } } else if (ext->newmail) - ext->newmail = 0; + ext->newmail = 0; } static void @@ -670,11 +674,11 @@ ccw_chat_check_term_resize(CCW_CTX *ctx) // detect terminal resize if (ext->old_rows != t_lines || - ext->old_cols != t_columns) + ext->old_cols != t_columns) { - ext->old_rows = t_lines; - ext->old_cols = t_columns; - ctx->reset_scr = YEA; + ext->old_rows = t_lines; + ext->old_cols = t_columns; + ctx->reset_scr = YEA; } } @@ -691,7 +695,7 @@ ccw_chat_send(CCW_CTX *ctx, const char *buf) static int ccw_chat_send_bye(CCW_CTX *ctx) { - return ccw_chat_send(ctx, "/b"); // protocol: bye + return ccw_chat_send(ctx, "/b"); // protocol: bye } static void @@ -699,10 +703,10 @@ ccw_chat_header(CCW_CTX *ctx) { prints(ANSI_COLOR(1;37;46) " �ͤѫ� [%-*s] " - ANSI_COLOR(45) " ���D: %-*s" ANSI_RESET, - CHAT_ROOM_LEN, ctx->remote_id, - t_columns - CHAT_ROOM_LEN - 20, - ccw_chat_get_ext(ctx)->topic); + ANSI_COLOR(45) " ���D: %-*s" ANSI_RESET, + CHAT_ROOM_LEN, ctx->remote_id, + t_columns - CHAT_ROOM_LEN - 20, + ccw_chat_get_ext(ctx)->topic); } static void @@ -713,19 +717,19 @@ ccw_chat_footer(CCW_CTX *ctx) // a little weird, but this looks like the best place to do ZA here... if (ZA_Waiting()) { - // process ZA - VREFSCR scr = vscr_save(); - add_io(0, 0); + // process ZA + VREFSCR scr = vscr_save(); + add_io(0, 0); - ZA_Enter(); + ZA_Enter(); - add_io(ctx->fd, 0); - vscr_restore(scr); + add_io(ctx->fd, 0); + vscr_restore(scr); } // draw real footer vs_footer("�i�ͤѫǡj", - " (PgUp/PgDn)�^�U�ͤѰO�� (Ctrl-Z)�ֳt����\t(Ctrl-C)���}�ͤѫ�"); + " (PgUp/PgDn)�^�U�ͤѰO�� (Ctrl-Z)�ֳt����\t(Ctrl-C)���}�ͤѫ�"); } static void @@ -754,58 +758,61 @@ ccw_chat_recv(CCW_CTX *ctx) { int c, len; char *bptr; - ccw_chat_ext *cb = ccw_chat_get_ext(ctx); + ccw_chat_ext *ext = ccw_chat_get_ext(ctx); - len = sizeof(cb->buf) - cb->bufstart - 1; - if ((c = recv(ctx->fd, cb->buf + cb->bufstart, len, 0)) <= 0) - return -1; - c += cb->bufstart; + // ext->buf may contain up to ext->buf_remains bytes of data. + // xchatd protocol: msg NUL /command NUL ... - bptr = cb->buf; + len = sizeof(ext->buf) - ext->buf_remains - 1; + if ((c = recv(ctx->fd, ext->buf + ext->buf_remains, len, 0)) <= 0) + return -1; + c += ext->buf_remains; + + bptr = ext->buf; while (c > 0) { - len = strlen(bptr) + 1; - if (len > c && (unsigned)len < (sizeof(cb->buf)/ 2) ) - break; - - if (*bptr == '/') { - switch (bptr[1]) { - case 'c': - ccw_reset_scr(ctx); - break; - case 'n': - strlcpy(ctx->local_id, bptr+2, CHAT_ID_LEN+1); - DBCS_safe_trim(ctx->local_id); - ccw_prompt(ctx); - break; - case 'r': - strlcpy(ctx->remote_id, bptr+2, CHAT_ROOM_LEN+1); - DBCS_safe_trim(ctx->remote_id); - ccw_header(ctx); - break; - case 't': - { - ccw_chat_ext *ext = ccw_chat_get_ext(ctx); - strlcpy(ext->topic, bptr+2, CHAT_TOPIC_LEN+1); - DBCS_safe_trim(ext->topic); - ccw_header(ctx); - } - - } - } else { - // received something, let's print it. - if (*bptr != '>' || PERM_HIDE(currutmp)) - ccw_add_line(ctx, bptr, CCW_REMOTE); - } - - c -= len; - bptr += len; + len = strlen(bptr) + 1; + if (len > c && (unsigned)len < (sizeof(ext->buf)/ 2) ) + break; + + if (*bptr == '/') { + switch (bptr[1]) { + case 'c': + ccw_reset_scr(ctx); + break; + case 'n': + strlcpy(ctx->local_id, bptr+2, CHAT_ID_LEN+1); + DBCS_safe_trim(ctx->local_id); + ccw_prompt(ctx); + break; + case 'r': + strlcpy(ctx->remote_id, bptr+2, CHAT_ROOM_LEN+1); + DBCS_safe_trim(ctx->remote_id); + ccw_header(ctx); + break; + case 't': + { + ccw_chat_ext *ext = ccw_chat_get_ext(ctx); + strlcpy(ext->topic, bptr+2, CHAT_TOPIC_LEN+1); + DBCS_safe_trim(ext->topic); + ccw_header(ctx); + } + + } + } else { + // received something, let's print it. + if (*bptr != '>' || PERM_HIDE(currutmp)) + ccw_add_line(ctx, bptr, CCW_REMOTE); + } + + c -= len; + bptr += len; } if (c > 0) { - memmove(cb->buf, bptr, sizeof(cb->buf)-(bptr-cb->buf)); - cb->bufstart = len - 1; + memmove(ext->buf, bptr, sizeof(ext->buf)-(bptr-ext->buf)); + ext->buf_remains = len - 1; } else - cb->bufstart = 0; + ext->buf_remains = 0; return 0; } @@ -820,28 +827,28 @@ ccw_chat_anti_flood(CCW_CTX *ctx) syncnow(); if (now - lasttime < 3 ) { - // 3 �����~�b���O���檺 ((25-5)/2) - if( ++flood > 10 ) - { - // flush all input! - unsigned char garbage[STRLEN]; - drop_input(); - while (wait_input(1, 0)) - { - if (num_in_buf()) - drop_input(); - else - tty_read(garbage, sizeof(garbage)); - } - drop_input(); - vmsg("�ФŤj�q�ŶK�γy���~�O�����ĪG�C"); - - // log? - sleep(2); - } + // 3 �����~�b���O���檺 ((25-5)/2) + if( ++flood > 10 ) + { + // flush all input! + unsigned char garbage[STRLEN]; + drop_input(); + while (wait_input(1, 0)) + { + if (num_in_buf()) + drop_input(); + else + tty_read(garbage, sizeof(garbage)); + } + drop_input(); + vmsg("�ФŤj�q�ŶK�γy���~�O�����ĪG�C"); + + // log? + sleep(2); + } } else { - lasttime = now; - flood = 0; + lasttime = now; + flood = 0; } #endif // anti-flood } @@ -857,81 +864,81 @@ ccw_chat_peek_cmd(CCW_CTX *ctx, const char *buf, int local) if (ccw_partial_match(buf, "help")) { - static const char *hlp_op[] = { - "[/f]lag [+-][ls]", "�]�w��w�B���K���A", - "[/i]nvite <id>", "�ܽ� <id> �[�J�ͤѫ�", - "[/k]ick <id>", "�N <id> ��X�ͤѫ�", - "[/o]p <id>", "�N Op ���v�O�ಾ�� <id>", - "[/t]opic <text>", "���Ӹ��D", - "[/w]all", "�s�� (�����M��)", - " /ban <userid>", "�ڵ� <userid> �A���i�J���ͤѫ� (�[�J�¦W��)", - " /unban <userid>", "�� <userid> ���X�¦W��", - NULL, - }, *hlp[] = { - " /help op", "�ͤѫǺz���M�Ϋ��O", - "[//]help", "MUD-like ����ʵ�", - "[/a]ct <msg>", "���@�Ӱʧ@", - "[/b]ye [msg]", "�D�O", - "[/c]lear", "�M���ù�", - "[/j]oin <room>", "�إߩΥ[�J�ͤѫ�", - "[/l]ist [room]", "�C�X�ͤѫǨϥΪ�", - "[/m]sg <id> <msg>", "�� <id> ��������", - "[/n]ick <id>", "�N�ͤѥN������ <id>", - "[/p]ager", "�����I�s��", - "[/r]oom ", "�C�X�@��ͤѫ�", - "[/w]ho", "�C�X���ͤѫǨϥΪ�", - " /whoin <room>", "�C�X�ͤѫ�<room> ���ϥΪ�", - " /ignore <userid>", "�������w�ϥΪ̪��T��", - " /unignore <userid>", "��������w�ϥΪ̪��T��", - NULL, - }; - - const char **p = hlp; - char msg[STRLEN]; - - if (strcasestr(buf, " op")) - { - p = hlp_op; - ccw_print_line(ctx, "�ͤѫǺz���M�Ϋ��O", CCW_LOCAL_MSG); - } - while (*p) - { - snprintf(msg, sizeof(msg), " %-20s- %s", p[0], p[1]); - ccw_print_line(ctx, msg, CCW_LOCAL_MSG); - p += 2; - } - return 1; + static const char *hlp_op[] = { + "[/f]lag [+-][ls]", "�]�w��w�B���K���A", + "[/i]nvite <id>", "�ܽ� <id> �[�J�ͤѫ�", + "[/k]ick <id>", "�N <id> ��X�ͤѫ�", + "[/o]p <id>", "�N Op ���v�O�ಾ�� <id>", + "[/t]opic <text>", "���Ӹ��D", + "[/w]all", "�s�� (�����M��)", + " /ban <userid>", "�ڵ� <userid> �A���i�J���ͤѫ� (�[�J�¦W��)", + " /unban <userid>", "�� <userid> ���X�¦W��", + NULL, + }, *hlp[] = { + " /help op", "�ͤѫǺz���M�Ϋ��O", + "[//]help", "MUD-like ����ʵ�", + "[/a]ct <msg>", "���@�Ӱʧ@", + "[/b]ye [msg]", "�D�O", + "[/c]lear", "�M���ù�", + "[/j]oin <room>", "�إߩΥ[�J�ͤѫ�", + "[/l]ist [room]", "�C�X�ͤѫǨϥΪ�", + "[/m]sg <id> <msg>", "�� <id> ��������", + "[/n]ick <id>", "�N�ͤѥN������ <id>", + "[/p]ager", "�����I�s��", + "[/r]oom ", "�C�X�@��ͤѫ�", + "[/w]ho", "�C�X���ͤѫǨϥΪ�", + " /whoin <room>", "�C�X�ͤѫ�<room> ���ϥΪ�", + " /ignore <userid>", "�������w�ϥΪ̪��T��", + " /unignore <userid>", "��������w�ϥΪ̪��T��", + NULL, + }; + + const char **p = hlp; + char msg[STRLEN]; + + if (strcasestr(buf, " op")) + { + p = hlp_op; + ccw_print_line(ctx, "�ͤѫǺz���M�Ϋ��O", CCW_LOCAL_MSG); + } + while (*p) + { + snprintf(msg, sizeof(msg), " %-20s- %s", p[0], p[1]); + ccw_print_line(ctx, msg, CCW_LOCAL_MSG); + p += 2; + } + return 1; } if (ccw_partial_match(buf, "clear") || - ccw_partial_match(buf, "cls")) + ccw_partial_match(buf, "cls")) { - ccw_reset_scr(ctx); - return 1; + ccw_reset_scr(ctx); + return 1; } if (ccw_partial_match(buf, "date")) { - char genbuf[STRLEN]; - syncnow(); - snprintf(genbuf, sizeof(genbuf), - "�� " BBSNAME "�зǮɶ�: %s", Cdate(&now)); - ccw_add_line(ctx, genbuf, CCW_LOCAL_MSG); - return 1; + char genbuf[STRLEN]; + syncnow(); + snprintf(genbuf, sizeof(genbuf), + "�� " BBSNAME "�зǮɶ�: %s", Cdate(&now)); + ccw_add_line(ctx, genbuf, CCW_LOCAL_MSG); + return 1; } if (ccw_partial_match(buf, "pager")) { - char genbuf[STRLEN]; - currutmp->pager ++; - currutmp->pager %= PAGER_MODES; - snprintf(genbuf, sizeof(genbuf), "�� �z���I�s���w�]��: [%s]", - str_pager_modes[currutmp->pager]); - ccw_add_line(ctx, genbuf, CCW_LOCAL_MSG); - return 1; + char genbuf[STRLEN]; + currutmp->pager ++; + currutmp->pager %= PAGER_MODES; + snprintf(genbuf, sizeof(genbuf), "�� �z���I�s���w�]��: [%s]", + str_pager_modes[currutmp->pager]); + ccw_add_line(ctx, genbuf, CCW_LOCAL_MSG); + return 1; } if (ccw_partial_match(buf, "bye")) { - ccw_chat_send_bye(ctx); - ctx->abort = 1; - return 1; + ccw_chat_send_bye(ctx); + ctx->abort = 1; + return 1; } return 0; } @@ -940,7 +947,7 @@ static void ccw_chat_post_input(CCW_CTX *ctx, const char *buf, int local) { if (local != CCW_LOCAL) - return; + return; // send message to server if possible. ctx->abort = (ccw_chat_send(ctx, buf) <= 0); @@ -950,77 +957,77 @@ static int ccw_chat_peek_key(CCW_CTX *ctx, int key) { switch (key) { - case I_OTHERDATA: // incoming - { - if (ccw_chat_recv(ctx) == -1) - { - ccw_chat_send_bye(ctx); - ctx->abort = YEA; - return 1; - } - ccw_chat_check_newmail(ctx); - return 1; - } - - case Ctrl('C'): - { - VREFSCR scr = vscr_save(); - add_io(0, 0); - - if (vans("�T�w�n����ͤѶ�? [y/N]: ") == 'y') - ctx->abort = YEA; - - add_io(ctx->fd, 0); - vscr_restore(scr); - - // ccw_footer(ctx); - } - // notify remote user - if (ctx->abort) - ccw_chat_send_bye(ctx); - return 1; - - case Ctrl('I'): - { - VREFSCR scr = vscr_save(); - add_io(0, 0); - - t_idle(); - - add_io(ctx->fd, 0); - vscr_restore(scr); - } - return 1; - - case KEY_PGUP: - case KEY_PGDN: - if (ctx->log && ctx->log_fpath) - { - VREFSCR scr = vscr_save(); - add_io(0, 0); - - fflush(ctx->log); - more(ctx->log_fpath, YEA); - - add_io(ctx->fd, 0); - vscr_restore(scr); - } - return 1; - - // Support ZA because chat is mostly independent and secure. - case Ctrl('Z'): - { - int za = 0; - VREFCUR cur = vcur_save(); - add_io(0, 0); - za = ZA_Select(); - ccw_footer(ctx); - add_io(ctx->fd, 0); - vcur_restore(cur); - if (za) - ctx->abort_vget = 1; - return 1; - } + case I_OTHERDATA: // incoming + { + if (ccw_chat_recv(ctx) == -1) + { + ccw_chat_send_bye(ctx); + ctx->abort = YEA; + return 1; + } + ccw_chat_check_newmail(ctx); + return 1; + } + + case Ctrl('C'): + { + VREFSCR scr = vscr_save(); + add_io(0, 0); + + if (vans("�T�w�n����ͤѶ�? [y/N]: ") == 'y') + ctx->abort = YEA; + + add_io(ctx->fd, 0); + vscr_restore(scr); + + // ccw_footer(ctx); + } + // notify remote user + if (ctx->abort) + ccw_chat_send_bye(ctx); + return 1; + + case Ctrl('I'): + { + VREFSCR scr = vscr_save(); + add_io(0, 0); + + t_idle(); + + add_io(ctx->fd, 0); + vscr_restore(scr); + } + return 1; + + case KEY_PGUP: + case KEY_PGDN: + if (ctx->log && ctx->log_fpath) + { + VREFSCR scr = vscr_save(); + add_io(0, 0); + + fflush(ctx->log); + more(ctx->log_fpath, YEA); + + add_io(ctx->fd, 0); + vscr_restore(scr); + } + return 1; + + // Support ZA because chat is mostly independent and secure. + case Ctrl('Z'): + { + int za = 0; + VREFCUR cur = vcur_save(); + add_io(0, 0); + za = ZA_Select(); + ccw_footer(ctx); + add_io(ctx->fd, 0); + vcur_restore(cur); + if (za) + ctx->abort_vget = 1; + return 1; + } } return 0; } @@ -1029,73 +1036,72 @@ int ccw_chat(int fd) { char chatid[CHAT_ID_LEN+1] = "myid", - roomid[CHAT_ROOM_LEN+1] = "room"; + roomid[CHAT_ROOM_LEN+1] = "room"; char fpath[PATHLEN]; ccw_chat_ext ext = { - .old_rows = t_lines, - .old_cols = t_columns, + .old_rows = t_lines, + .old_cols = t_columns, }; CCW_CTX ctx = { - .fd = fd, - .abort = NA, - - .log = NULL, - .log_fpath = fpath, - .local_echo = NA, - .MAX_INPUT_LEN = STRLEN - CHAT_ID_LEN - 3, // 3 for ": " - .remote_id = roomid, - .local_id = chatid, - .arg = &ext, - .sep_msg = " /h �d�߫��O /b ���} ", - - .header = ccw_chat_header, - .footer = ccw_chat_footer, - .prompt = ccw_chat_prompt, - .print_line = ccw_chat_print_line, - .log_line = ccw_chat_log_line, - - .peek_key = ccw_chat_peek_key, - .peek_cmd = ccw_chat_peek_cmd, - .post_input = ccw_chat_post_input, + .fd = fd, + .abort = NA, + + .log = NULL, + .log_fpath = fpath, + .local_echo = NA, + .MAX_INPUT_LEN = STRLEN - CHAT_ID_LEN - 3, // 3 for ": " + .remote_id = roomid, + .local_id = chatid, + .arg = &ext, + .sep_msg = " /h �d�߫��O /b ���} ", + + .header = ccw_chat_header, + .footer = ccw_chat_footer, + .prompt = ccw_chat_prompt, + .print_line = ccw_chat_print_line, + .log_line = ccw_chat_log_line, + + .peek_key = ccw_chat_peek_key, + .peek_cmd = ccw_chat_peek_cmd, + .post_input = ccw_chat_post_input, }; // initialize nick while (1) { - const char *err = "�L�k�ϥΦ��N��"; - char cmd[200]; - - getdata(b_lines - 1, 0, "�п�J�Q�ϥΪ��ͤѼʺ�: ", chatid, sizeof(chatid), DOECHO); - if(!chatid[0]) - strlcpy(chatid, cuser.userid, sizeof(chatid)); - - // safe truncate - DBCS_safe_trim(chatid); - - // login format: /! UserID ChatID password - snprintf(cmd, sizeof(cmd), "/! %s %s %s", cuser.userid, chatid, cuser.passwd); - ccw_chat_send(&ctx, cmd); - if (recv(ctx.fd, cmd, 3, 0) != 3) { - close(ctx.fd); - vmsg("�t�ο��~�C"); - return 0; - } - - if (strcmp(cmd, CHAT_LOGIN_OK) == 0) - break; - else if (!strcmp(cmd, CHAT_LOGIN_EXISTS)) - err = "�o�ӥN���w�g���H�ΤF"; - else if (!strcmp(cmd, CHAT_LOGIN_INVALID)) - err = "�o�ӥN���O���~��"; - else if (!strcmp(cmd, CHAT_LOGIN_BOGUS)) - err = "�ФŬ��������i�J�ͤѫ� !!"; - - move(b_lines - 2, 0); - outs(err); - clrtoeol(); - bell(); + const char *err = "�L�k�ϥΦ��N��"; + char cmd[200]; + + getdata(b_lines - 1, 0, "�п�J�Q�ϥΪ��ͤѼʺ�: ", chatid, sizeof(chatid), DOECHO); + if(!chatid[0]) + strlcpy(chatid, cuser.userid, sizeof(chatid)); + + // safe truncate + DBCS_safe_trim(chatid); + + // login format: /! UserID ChatID password + snprintf(cmd, sizeof(cmd), "/! %s %s %s", cuser.userid, chatid, cuser.passwd); + ccw_chat_send(&ctx, cmd); + if (recv(ctx.fd, cmd, 3, 0) != 3) { + close(ctx.fd); + vmsg("�t�ο��~�C"); + return 0; + } + + if (strcmp(cmd, CHAT_LOGIN_OK) == 0) + break; + else if (!strcmp(cmd, CHAT_LOGIN_EXISTS)) + err = "�o�ӥN���w�g���H�ΤF"; + else if (!strcmp(cmd, CHAT_LOGIN_INVALID)) + err = "�o�ӥN���O���~��"; + else if (!strcmp(cmd, CHAT_LOGIN_BOGUS)) + err = "�ФŬ��������i�J�ͤѫ� !!"; + + move(b_lines - 2, 0); + outs(err); + clrtoeol(); + bell(); } - add_io(fd, 0); setutmpmode(CHATING); currutmp->in_chat = YEA; strlcpy(currutmp->chatid, chatid, sizeof(currutmp->chatid)); @@ -1106,13 +1112,19 @@ ccw_chat(int fd) assert(ctx.log); fprintf(ctx.log, "[%s] �i�J�ͤѫ�:\n", Cdatelite(&now)); + // main processor + add_io(fd, 0); ccw_process(&ctx); - close(fd); + // clean network resource add_io(0, 0); + close(fd); currutmp->in_chat = currutmp->chatid[0] = 0; + // close log file ccw_talkchat_close_log(&ctx, NA, YEA); return 0; } + +// vim:sw=4:ts=8:et |