diff options
Diffstat (limited to 'mbbsd/stuff.c')
-rw-r--r-- | mbbsd/stuff.c | 828 |
1 files changed, 0 insertions, 828 deletions
diff --git a/mbbsd/stuff.c b/mbbsd/stuff.c deleted file mode 100644 index 2349a68d..00000000 --- a/mbbsd/stuff.c +++ /dev/null @@ -1,828 +0,0 @@ -/* $Id$ */ -#include "bbs.h" - -/* ----------------------------------------------------- */ -/* set file path for boards/user home */ -/* ----------------------------------------------------- */ -static const char * const str_home_file = "home/%c/%s/%s"; -static const char * const str_board_file = "boards/%c/%s/%s"; -static const char * const str_board_n_file = "boards/%c/%s/%s.%d"; - - -static const char * const str_dotdir = FN_DIR; - -/* XXX set*() all assume buffer size = PATHLEN */ -void -sethomepath(char *buf, const char *userid) -{ - assert(is_validuserid(userid)); - snprintf(buf, PATHLEN, "home/%c/%s", userid[0], userid); -} - -void -sethomedir(char *buf, const char *userid) -{ - assert(is_validuserid(userid)); - snprintf(buf, PATHLEN, str_home_file, userid[0], userid, str_dotdir); -} - -void -sethomeman(char *buf, const char *userid) -{ - assert(is_validuserid(userid)); - snprintf(buf, PATHLEN, str_home_file, userid[0], userid, "man"); -} - - -void -sethomefile(char *buf, const char *userid, const char *fname) -{ - assert(is_validuserid(userid)); - assert(fname[0]); - snprintf(buf, PATHLEN, str_home_file, userid[0], userid, fname); -} - -void -setuserfile(char *buf, const char *fname) -{ - assert(is_validuserid(cuser.userid)); - assert(fname[0]); - snprintf(buf, PATHLEN, str_home_file, cuser.userid[0], cuser.userid, fname); -} - -void -setapath(char *buf, const char *boardname) -{ - //assert(boardname[0]); - snprintf(buf, PATHLEN, "man/boards/%c/%s", boardname[0], boardname); -} - -void -setadir(char *buf, const char *path) -{ - //assert(path[0]); - snprintf(buf, PATHLEN, "%s/%s", path, str_dotdir); -} - -void -setbpath(char *buf, const char *boardname) -{ - //assert(boardname[0]); - snprintf(buf, PATHLEN, "boards/%c/%s", boardname[0], boardname); -} - -void -setbdir(char *buf, const char *boardname) -{ - //assert(boardname[0]); - snprintf(buf, PATHLEN, str_board_file, boardname[0], boardname, - (currmode & MODE_DIGEST ? fn_mandex : str_dotdir)); -} - -void -setbfile(char *buf, const char *boardname, const char *fname) -{ - //assert(boardname[0]); - assert(fname[0]); - snprintf(buf, PATHLEN, str_board_file, boardname[0], boardname, fname); -} - -void -setbnfile(char *buf, const char *boardname, const char *fname, int n) -{ - //assert(boardname[0]); - assert(fname[0]); - snprintf(buf, PATHLEN, str_board_n_file, boardname[0], boardname, fname, n); -} - -/* - * input direct - * output buf: copy direct - * fname: direct 的檔名部分 - */ -void -setdirpath(char *buf, const char *direct, const char *fname) -{ - char *p; - strcpy(buf, direct); - p = strrchr(buf, '/'); - assert(p); - strlcpy(p + 1, fname, PATHLEN-(p+1-buf)); -} - -/** - * 給定文章標題 title,傳回指到主題的部分的指標。 - * @param title - */ -char * -subject(char *title) -{ - if (!strncasecmp(title, str_reply, 3)) { - title += 3; - if (*title == ' ') - title++; - } - return title; -} - -int is_validuserid(const char *id) -{ - int len, i; - if(id==NULL) - return 0; - len = strlen(id); - - if (len < 2 || len>IDLEN) - return 0; - - if (!isalpha(id[0])) - return 0; - for (i = 1; i < len; i++) - if (!isalnum(id[i])) - return 0; - return 1; -} - -int -is_uBM(const char *list, const char *id) -{ - register int len; - - if (list[0] == '[') - list++; - if (list[0] > ' ') { - len = strlen(id); - do { - if (!strncasecmp(list, id, len)) { - list += len; - if ((*list == 0) || (*list == '/') || - (*list == ']') || (*list == ' ')) - return 1; - } - if ((list = strchr(list, '/')) != NULL) - list++; - else - break; - } while (1); - } - return 0; -} - -int -is_BM(const char *list) -{ - if (is_uBM(list, cuser.userid)) { - cuser.userlevel |= PERM_BM; /* Ptt 自動加上BM的權利 */ - return 1; - } - return 0; -} - -int -userid_is_BM(const char *userid, const char *list) -{ - register int ch, len; - - // TODO merge with is_uBM - ch = list[0]; - if ((ch > ' ') && (ch < 128)) { - len = strlen(userid); - do { - if (!strncasecmp(list, userid, len)) { - ch = list[len]; - if ((ch == 0) || (ch == '/') || (ch == ']')) - return 1; - } - while ((ch = *list++)) { - if (ch == '/') - break; - } - } while (ch); - } - return 0; -} - -int -belong(const char *filelist, const char *key) -{ - return file_exist_record(filelist, key); -} - - -#ifndef _BBS_UTIL_C_ /* getdata_buf */ -time4_t -gettime(int line, time4_t dt, const char*head) -{ - char yn[7]; - int i; - struct tm *ptime = localtime4(&dt), endtime; - time_t t; - - memcpy(&endtime, ptime, sizeof(struct tm)); - snprintf(yn, sizeof(yn), "%4d", ptime->tm_year + 1900); - move(line, 0); outs(head); - i=strlen(head); - do { - getdata_buf(line, i, " 西元年:", yn, 5, LCECHO); - // signed: limited on (2037, ...) - // unsigned: limited on (..., 1970) - // let's restrict inside the boundary. - } while ((endtime.tm_year = atoi(yn) - 1900) < 70 || endtime.tm_year > 135); - snprintf(yn, sizeof(yn), "%d", ptime->tm_mon + 1); - do { - getdata_buf(line, i+15, "月:", yn, 3, LCECHO); - } while ((endtime.tm_mon = atoi(yn) - 1) < 0 || endtime.tm_mon > 11); - snprintf(yn, sizeof(yn), "%d", ptime->tm_mday); - do { - getdata_buf(line, i+24, "日:", yn, 3, LCECHO); - } while ((endtime.tm_mday = atoi(yn)) < 1 || endtime.tm_mday > 31); - snprintf(yn, sizeof(yn), "%d", ptime->tm_hour); - do { - getdata_buf(line, i+33, "時(0-23):", yn, 3, LCECHO); - } while ((endtime.tm_hour = atoi(yn)) < 0 || endtime.tm_hour > 23); - t = mktime(&endtime); - /* saturation check */ - if(t < 0) - t = 1; - if(t > INT_MAX) - t = INT_MAX; - return t; -} - -// synchronize 'now' -void syncnow(void) -{ -#ifdef OUTTA_TIMER - now = SHM->GV2.e.now; -#else - now = time(0); -#endif -} - -#endif - - -#ifndef _BBS_UTIL_C_ -/* 這一區都是有關於畫面處理的, 故 _BBS_UTIL_C_ 不須要 */ - -#ifdef PLAY_ANGEL -void -pressanykey_or_callangel(){ - int ch; - - outmsg( - ANSI_COLOR(1;34;44) " ▄▄▄▄ " - ANSI_COLOR(32) "H " ANSI_COLOR(36) "呼叫小天使" ANSI_COLOR(34) - " ▄▄▄▄" ANSI_COLOR(37;44) " 請按 " ANSI_COLOR(36) "空白鍵 " - ANSI_COLOR(37) "繼續 " ANSI_COLOR(1;34) - "▄▄▄▄▄▄▄▄▄▄▄▄▄▄ " ANSI_RESET); - do { - ch = igetch(); - if (ch == 'h' || ch == 'H'){ - CallAngel(); - break; - } - } while ((ch != ' ') && (ch != KEY_LEFT) && (ch != '\r') && (ch != '\n')); - move(b_lines, 0); - clrtoeol(); - refresh(); -} -#endif - -/** - * 給 printf format 的參數,印到最底下一行。 - * 傳回使用者的選擇(char)。 - */ -char -getans(const char *fmt,...) -{ - char msg[256]; - char ans[3]; - va_list ap; - va_start(ap, fmt); - vsnprintf(msg , sizeof(msg), fmt, ap); - va_end(ap); - - getdata(b_lines, 0, msg, ans, sizeof(ans), LCECHO); - return ans[0]; -} - -int -getkey(const char *fmt,...) -{ - char msg[256], i; - va_list ap; - va_start(ap, fmt); - i = vsnprintf(msg , sizeof(msg), fmt, ap); - va_end(ap); - return vmsg(msg); -} - -static const char *msg_pressanykey_full = - ANSI_COLOR(37;44) " 請按" ANSI_COLOR(36) " 任意鍵 " ANSI_COLOR(37) "繼續 " ANSI_COLOR(34); -#define msg_pressanykey_full_len (18) - - // what is 200/1431/506/201? -static const char* msg_pressanykey_trail = - ANSI_COLOR(33;46) " [按任意鍵繼續] " ANSI_RESET; -#define msg_pressanykey_trail_len (16+1+4) /* 4 for head */ - -int -vmsg(const char *msg) -{ - int len = msg ? strlen(msg) : 0; - int i = 0; - - if(len == 0) msg = NULL; - - move(b_lines, 0); - clrtoeol(); - - if(!msg) - { - /* msg_pressanykey_full */ - int w = (t_columns - msg_pressanykey_full_len - 8) / 2; - int pad = 0; - - outs(ANSI_COLOR(1;34;44) " "); - pad += 1; - for (i = 0; i < w; i += 2) - outs("▄"), pad+=2; - outs(msg_pressanykey_full), pad+= msg_pressanykey_full_len; - /* pad now points to position of current cursor. */ - pad = t_columns - pad -2 ; - /* pad is now those left . */ - if (pad > 0) - { - for (i = 0; i <= pad-2; i += 2) - outs("▄"); - if (i == pad-1) - outs(" "); - } - outs(ANSI_RESET); - } else { - /* msg_pressanykey_trail */ - outs(ANSI_COLOR(1;36;44) " ◆ "); - if(len >= t_columns - msg_pressanykey_trail_len) - len = t_columns - msg_pressanykey_trail_len; - while (i++ < len) - outc(*msg++); - i--; - while (i++ < t_columns - msg_pressanykey_trail_len) - outc(' '); - outs(msg_pressanykey_trail); - } - - do { - i = igetch(); - } while( i == 0 ); - - move(b_lines, 0); - clrtoeol(); - return i; -} - -int -vmsgf(const char *fmt,...) -{ - char msg[256]; - va_list ap; - va_start(ap, fmt); - vsnprintf(msg, sizeof(msg), fmt, ap); - va_end(ap); - msg[sizeof(msg)-1] = 0; - return vmsg(msg); -} - -/** - * 從第 y 列開始 show 出 filename 檔案中的前 lines 行。 - * mode 為 output 的模式,參數同 strip_ansi。 - * @param filename - * @param x - * @param lines - * @param mode: SHOWFILE_*, see modes.h - * @return 失敗傳回 0,否則為 1。 - * 2 表示有 PttPrints 碼 - */ -int -show_file(const char *filename, int y, int lines, int mode) -{ - FILE *fp; - char buf[1024]; - int ret = 1; - int strpmode = STRIP_ALL; - - if (mode & SHOWFILE_ALLOW_COLOR) - strpmode = ONLY_COLOR; - if (mode & SHOWFILE_ALLOW_MOVE) - strpmode = NO_RELOAD; - - if (y >= 0) - move(y, 0); - clrtoln(lines + y); - if ((fp = fopen(filename, "r"))) { - while (fgets(buf, sizeof(buf), fp) && lines--) - { - move(y++, 0); - if (mode == SHOWFILE_RAW) - { - outs(buf); - } - else if ((mode & SHOWFILE_ALLOW_STAR) && (strstr(buf, ESC_STR "*") != NULL)) - { - // because Ptt_prints escapes are not so often, - // let's try harder to detect it. - outs(Ptt_prints(buf, sizeof(buf), strpmode)); - ret = 2; - } else { - // ESC is very common... - strip_ansi(buf, buf, strpmode); - outs(buf); - } - } - fclose(fp); - outs(ANSI_RESET); // prevent some broken Welcome file - } else - return 0; - return ret; -} - -void -bell(void) -{ - char c; - - c = Ctrl('G'); - write(1, &c, 1); -} - -int -search_num(int ch, int max) -{ - int clen = 1, y = b_lines - msg_occupied; - char genbuf[10]; - - genbuf[0] = ch; genbuf[1] = 0; - clen = getdata_buf(y, 0, - " 跳至第幾項: ", genbuf, sizeof(genbuf)-1, NUMECHO); - - move(y, 0); clrtoeol(); - genbuf[clen] = '\0'; - if (genbuf[0] == '\0') - return -1; - clen = atoi(genbuf); - if (clen == 0) - return 0; - if (clen > max) - return max; - return clen - 1; -} - -/** - * 在螢幕左上角 show 出 "【title】" - * @param title - */ -void -stand_title(const char *title) -{ - clear(); - prints(ANSI_COLOR(1;37;46) "【 %s 】" ANSI_RESET "\n", title); -} - -void -cursor_show(int row, int column) -{ - move(row, column); - outs(STR_CURSOR); - move(row, column + 1); -} - -void -cursor_clear(int row, int column) -{ - move(row, column); - outs(STR_UNCUR); -} - -int -cursor_key(int row, int column) -{ - int ch; - - cursor_show(row, column); - ch = igetch(); - move(row, column); - outs(STR_UNCUR); - return ch; -} - -void -printdash(const char *mesg, int msglen) -{ - int head = 0, tail; - - if(msglen <= 0) - msglen = strlen(mesg); - - if (mesg) - head = (msglen + 1) >> 1; - - tail = head; - - while (head++ < t_columns/2-2) - outc('-'); - - if (tail) { - outc(' '); - if(mesg) outs(mesg); - outc(' '); - } - while (tail++ < t_columns/2-2) - outc('-'); - - outc('\n'); -} - -int -log_user(const char *fmt, ...) -{ - char msg[256], filename[256]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(msg , sizeof(msg), fmt, ap); - va_end(ap); - - sethomefile(filename, cuser.userid, "USERLOG"); - return log_filef(filename, LOG_CREAT, "%s: %s %s", cuser.userid, msg, Cdate(&now)); -} - -void -show_help(const char * const helptext[]) -{ - const char *str; - int i; - - clear(); - for (i = 0; (str = helptext[i]); i++) { - if (*str == '\0') - prints(ANSI_COLOR(1) "【 %s 】" ANSI_COLOR(0) "\n", str + 1); - else if (*str == '\01') - prints("\n" ANSI_COLOR(36) "【 %s 】" ANSI_RESET "\n", str + 1); - else - prints(" %s\n", str); - } -#ifdef PLAY_ANGEL - if (HasUserPerm(PERM_LOGINOK)) - pressanykey_or_callangel(); - else -#endif - pressanykey(); -} - -void -show_helpfile(const char *helpfile) -{ - clear(); - show_file((char *)helpfile, 0, b_lines, SHOWFILE_ALLOW_ALL); -#ifdef PLAY_ANGEL - if (HasUserPerm(PERM_LOGINOK)) - pressanykey_or_callangel(); - else -#endif - pressanykey(); -} - -#endif // _BBS_UTIL_C_ - -/* ----------------------------------------------------- */ -/* use mmap() to malloc large memory in CRITICAL_MEMORY */ -/* ----------------------------------------------------- */ -#ifdef CRITICAL_MEMORY -void *MALLOC(int size) -{ - int *p; - p = (int *)mmap(NULL, (size + 4), PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, -1, 0); - p[0] = size; -#if defined(DEBUG) && !defined(_BBS_UTIL_C_) - vmsgf("critical malloc %d bytes", size); -#endif - return (void *)&p[1]; -} - -void FREE(void *ptr) -{ - int size = ((int *)ptr)[-1]; - munmap((void *)(&(((int *)ptr)[-1])), size); -#if defined(DEBUG) && !defined(_BBS_UTIL_C_) - vmsgf("critical free %d bytes", size); -#endif -} -#endif - - -unsigned -DBCS_StringHash(const char *s) -{ - return fnv1a_32_dbcs_strcase(s, FNV1_32_INIT); -} - -inline int *intbsearch(int key, const int *base0, int nmemb) -{ - /* 改自 /usr/src/lib/libc/stdlib/bsearch.c , - 專給搜 int array 用的, 不透過 compar function 故較快些 */ - const char *base = (const char *)base0; - size_t lim; - int *p; - - for (lim = nmemb; lim != 0; lim >>= 1) { - p = (int *)(base + (lim >> 1) * 4); - if( key == *p ) - return p; - if( key > *p ){/* key > p: move right */ - base = (char *)p + 4; - lim--; - } /* else move left */ - } - return (NULL); -} - -inline unsigned int * -uintbsearch(const unsigned int key, const unsigned int *base0, const int nmemb) -{ - /* 改自 /usr/src/lib/libc/stdlib/bsearch.c , - 專給搜 int array 用的, 不透過 compar function 故較快些 */ - const char *base = (const char *)base0; - size_t lim; - unsigned int *p; - - for (lim = nmemb; lim != 0; lim >>= 1) { - p = (unsigned int *)(base + (lim >> 1) * 4); - if( key == *p ) - return p; - if( key > *p ){/* key > p: move right */ - base = (char *)p + 4; - lim--; - } /* else move left */ - } - return (NULL); -} - -/* AIDS */ -aidu_t fn2aidu(char *fn) -{ - aidu_t aidu = 0; - aidu_t type = 0; - aidu_t v1 = 0; - aidu_t v2 = 0; - char *sp = fn; - - if(fn == NULL) - return 0; - - switch(*(sp ++)) - { - case 'M': - type = 0; - break; - case 'G': - type = 1; - break; - default: - return 0; - break; - } - - if(*(sp ++) != '.') - return 0; - v1 = strtoul(sp, &sp, 10); - if(sp == NULL) - return 0; - if(*sp != '.' || *(sp + 1) != 'A') - return 0; - sp += 2; - if(*(sp ++) == '.') - { - v2 = strtoul(sp, &sp, 16); - if(sp == NULL) - return 0; - } - aidu = ((type & 0xf) << 44) | ((v1 & 0xffffffff) << 12) | (v2 & 0xfff); - - return aidu; -} - -/* IMPORTANT: - * size of buf must be at least 8+1 bytes - */ -char *aidu2aidc(char *buf, aidu_t aidu) -{ - const char aidu2aidc_table[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_"; - const int aidu2aidc_tablesize = sizeof(aidu2aidc_table) - 1; - char *sp = buf + 8; - aidu_t v; - - *(sp --) = '\0'; - while(sp >= buf) - { - /* FIXME: 能保證 aidu2aidc_tablesize 是 2 的冪次的話, - 這裡可以改用 bitwise operation 做 */ - v = aidu % aidu2aidc_tablesize; - aidu = aidu / aidu2aidc_tablesize; - *(sp --) = aidu2aidc_table[v]; - } - return buf; -} - -/* IMPORTANT: - * size of fn must be at least FNLEN bytes - */ -char *aidu2fn(char *fn, aidu_t aidu) -{ - aidu_t type = ((aidu >> 44) & 0xf); - aidu_t v1 = ((aidu >> 12) & 0xffffffff); - aidu_t v2 = (aidu & 0xfff); - - if(fn == NULL) - return NULL; - snprintf(fn, FNLEN - 1, "%c.%d.A.%03X", ((type == 0) ? 'M' : 'G'), (unsigned int)v1, (unsigned int)v2); - fn[FNLEN - 1] = '\0'; - return fn; -} - -aidu_t aidc2aidu(char *aidc) -{ - char *sp = aidc; - aidu_t aidu = 0; - - if(aidc == NULL) - return 0; - - while(*sp != '\0' && /* ignore trailing spaces */ *sp != ' ') - { - aidu_t v = 0; - /* FIXME: 查表法會不會比較快? */ - if(*sp >= '0' && *sp <= '9') - v = *sp - '0'; - else if(*sp >= 'A' && *sp <= 'Z') - v = *sp - 'A' + 10; - else if(*sp >= 'a' && *sp <= 'z') - v = *sp - 'a' + 36; - else if(*sp == '-') - v = 62; - else if(*sp == '_') - v = 63; - else - return 0; - aidu <<= 6; - aidu |= (v & 0x3f); - sp ++; - } - - return aidu; -} - -int search_aidu(char *bfile, aidu_t aidu) -{ - char fn[FNLEN]; - int fd; - fileheader_t fhs[64]; - int len, i; - int pos = 0; - int found = 0; - int lastpos = 0; - - if(aidu2fn(fn, aidu) == NULL) - return -1; - if((fd = open(bfile, O_RDONLY, 0)) < 0) - return -1; - - while(!found && (len = read(fd, fhs, sizeof(fhs))) > 0) - { - len /= sizeof(fileheader_t); - for(i = 0; i < len; i ++) - { - int l; - if(strcmp(fhs[i].filename, fn) == 0 || - ((aidu & 0xfff) == 0 && (l = strlen(fhs[i].filename)) > 6 && - strncmp(fhs[i].filename, fn, l) == 0)) - { - if(fhs[i].filemode & FILE_BOTTOM) - { - lastpos = pos; - } - else - { - found = 1; - break; - } - } - pos ++; - } - } - close(fd); - - return (found ? pos : (lastpos ? lastpos : -1)); -} -/* end of AIDS */ |