diff options
52 files changed, 1106 insertions, 1171 deletions
diff --git a/include/bbs.h b/include/bbs.h index 8d51000a..ead0861e 100644 --- a/include/bbs.h +++ b/include/bbs.h @@ -43,11 +43,10 @@ extern "C" { /* our header */ #include "config.h" -#ifdef TIMET64 -typedef uint32_t time4_t; -#else -typedef time_t time4_t; -#endif + +#include "libbbsutil.h" +#include "libbbs.h" + #include "ansi.h" #include "statistic.h" #include "uflags.h" diff --git a/include/common.h b/include/common.h index 34b18bf0..a6fb23ec 100644 --- a/include/common.h +++ b/include/common.h @@ -229,8 +229,6 @@ #define REPLYING 0 #define RECVINREPLYING 1 -#define LOG_CREAT 1 -#define LOG_VF 2 #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) diff --git a/include/libbbs.h b/include/libbbs.h new file mode 100644 index 00000000..de042a03 --- /dev/null +++ b/include/libbbs.h @@ -0,0 +1,7 @@ +#ifndef _LIBBBS_H_ +#define _LIBBBS_H_ + +extern int give_tax(int money); +extern const char* money_level(int money); + +#endif diff --git a/include/libbbsutil.h b/include/libbbsutil.h new file mode 100644 index 00000000..8f9ac4f3 --- /dev/null +++ b/include/libbbsutil.h @@ -0,0 +1,88 @@ +#ifndef _LIBBBSUTIL_H_ +#define _LIBBBSUTIL_H_ + +#include <stdint.h> +#include <sys/types.h> +#ifdef __GNUC__ +#define GCC_CHECK_FORMAT(a,b) __attribute__ ((format (printf, a, b))) +#else +#define GCC_CHECK_FORMAT(a,b) +#endif +enum STRIP_FLAG { + STRIP_ALL = 0, ONLY_COLOR, NO_RELOAD +}; +enum LOG_FLAG { + LOG_CREAT = 1, +}; + + +#ifdef TIMET64 +typedef int32_t time4_t; +#else +typedef time_t time4_t; +#endif + +/* file.c */ +extern off_t dashs(const char *fname); +time4_t dasht(const char *fname); +extern int dashl(const char *fname); +extern int dashf(const char *fname); +extern int dashd(const char *fname); +extern int copy_file_to_file(const char *src, const char *dst); +extern int copy_file_to_dir(const char *src, const char *dst); +extern int copy_dir_to_dir(const char *src, const char *dst); +extern int copy_file(const char *src, const char *dst); +extern int Rename(const char *src, const char *dst); +extern int Copy(const char *src, const char *dst); +extern int CopyN(const char *src, const char *dst, int n); +extern int AppendTail(const char *src, const char *dst, int off); +extern int Link(const char *src, const char *dst); + +/* lock.c */ +extern void PttLock(int fd, int start, int size, int mode); + +/* net.c */ +extern unsigned int ipstr2int(const char *ip); +extern int tobind(const char * host, int port); +extern int toconnect(const char *host, int port); +extern int toread(int fd, void *buf, int len); +extern int towrite(int fd, const void *buf, int len); + +/* sort.c */ +extern int cmp_int(const void *a, const void *b); +extern int cmp_int_desc(const void * a, const void * b); + +/* string.h */ +extern void str_lower(char *t, const char *s); +extern void trim(char *buf); +extern void chomp(char *src); +extern int strip_blank(char *cbuf, char *buf); +extern int strip_ansi(char *buf, const char *str, enum STRIP_FLAG flag); +extern int strlen_noansi(const char *s); +extern void strip_nonebig5(unsigned char *str, int maxlen); +extern int invalid_pname(const char *str); +extern int is_number(const char *p); +extern unsigned StringHash(const char *s); +extern char * qp_encode (char *s, size_t slen, const char *d, const char *tocode); + +/* time.c */ +extern int is_leap_year(int year); +extern int getHoroscope(int m, int d); +extern char* Cdate(const time4_t *clock); +extern char* Cdatelite(const time4_t *clock); +extern char* Cdatedate(const time4_t * clock); +extern char* my_ctime(const time4_t * t, char *ans, int len); +#ifdef TIMET64 + struct tm *localtime4(const time4_t *); + time4_t time4(time4_t *); + char *ctime4(const time4_t *); +#else + #define localtime4(a) localtime(a) + #define time4(a) time(a) + #define ctime4(a) ctime(a) +#endif + +extern int log_filef(const char *fn, int flag, const char *fmt,...) GCC_CHECK_FORMAT(3,4); +extern int log_file(const char *fn, int flag, const char *msg); + +#endif diff --git a/include/modes.h b/include/modes.h index b5bc9833..24b8a01a 100644 --- a/include/modes.h +++ b/include/modes.h @@ -155,13 +155,11 @@ #define AUTHOR_PREV (RS_AUTHOR) /* DBCS aware modes */ -enum { +enum _DBCS_STATUS { DBCS_ASCII, DBCS_LEADING, DBCS_TRAILING, -} _DBCS_STATUS; - -enum {STRIP_ALL = 0, ONLY_COLOR, NO_RELOAD}; +}; #define SIG_PK 0 #define SIG_TALK 1 diff --git a/include/proto.h b/include/proto.h index e1985ce6..f62c1e7e 100644 --- a/include/proto.h +++ b/include/proto.h @@ -62,7 +62,6 @@ int inc_badsale(const char *, int num); /* bbs */ void delete_allpost(const char *userid); int invalid_brdname(const char *brd); -void chomp(char *src); int del_range(int ent, const fileheader_t *fhdr, const char *direct); int cmpfowner(fileheader_t *fhdr); int b_note_edit_bname(int bid); @@ -327,20 +326,12 @@ int getdata_str(int line, int col, const char *prompt, char *buf, int len, int e int getdata_buf(int line, int col, const char *prompt, char *buf, int len, int echo); void add_io(int fd, int timeout); void oflush(void); -int strip_ansi(char *buf, const char *str, int mode); -void strip_nonebig5(unsigned char *str, int maxlen); int oldgetdata(int line, int col, const char *prompt, char *buf, int len, int echo); void output(const char *s, int len); int num_in_buf(void); int ochar(int c); -int strlen_noansi(const char *buf); /* kaede */ -int Rename(const char* src, const char* dst); -int Copy(const char *src, const char *dst); -int CopyN(const char *src, const char *dst, int n); -int AppendTail(const char *src, const char *dst, int off); -int Link(const char* src, const char* dst); char *Ptt_prints(char *str, size_t size, int mode); char *my_ctime(const time4_t *t, char *ans, int len); @@ -600,7 +591,6 @@ void grayout_lines(int start, int end, int level); #define not_alnum(ch) (ch < '0' || (ch > '9' && ch < 'A') || (ch > 'Z' && ch < 'a') || ch > 'z') #define pressanykey() vmsg(NULL) int log_user(const char *fmt, ...) GCC_CHECK_FORMAT(1,2); -unsigned int ipstr2int(const char *ip); time4_t gettime(int line, time4_t dt, const char* head); void setcalfile(char *buf, char *userid); void stand_title(const char *title); @@ -608,43 +598,30 @@ char getans(const char *fmt,...) GCC_CHECK_FORMAT(1,2); int getkey(const char *fmt,...) GCC_CHECK_FORMAT(1,2); int vmsgf(const char *fmt,...) GCC_CHECK_FORMAT(1,2); int vmsg(const char *msg); -void trim(char *buf); int show_file(const char *filename, int y, int lines, int mode); void bell(void); void setbpath(char *buf, const char *boardname); -int dashf(const char *fname); void sethomepath(char *buf, const char *userid); void sethomedir(char *buf, const char *userid); -char *Cdate(const time4_t *clock); void sethomefile(char *buf, const char *userid, const char *fname); -int log_file(const char *fn, int flag, const char *fmt,...); -void str_lower(char *t, const char *s); int cursor_key(int row, int column); int search_num(int ch, int max); void setuserfile(char *buf, const char *fname); int is_BM(const char *list); -time4_t dasht(const char *fname); -int dashd(const char *fname); -int invalid_pname(const char *str); void setbdir(char *buf, const char *boardname); void setbfile(char *buf, const char *boardname, const char *fname); void setbnfile(char *buf, const char *boardname, const char *fname, int n); -int dashl(const char *fname); char *subject(char *title); +int is_validuserid(const char *id); void setdirpath(char *buf, const char *direct, const char *fname); int str_checksum(const char *str); void show_help(const char * const helptext[]); void show_helpfile(const char * helpfile); -int copy_file(const char *src, const char *dst); int belong(const char *filelist, const char *key); -char *Cdatedate(const time4_t *clock); void sethomeman(char *buf, const char *userid); -off_t dashs(const char *fname); void cursor_clear(int row, int column); void cursor_show(int row, int column); void printdash(const char *mesg, int msglen); -char *Cdatelite(const time4_t *clock); -int is_validuserid(const char *ident); int userid_is_BM(const char *userid, const char *list); int is_uBM(const char *list, const char *id); inline int *intbsearch(int key, const int *base0, int nmemb); @@ -657,24 +634,9 @@ int qsort_intcompar(const void *a, const void *b); void *MALLOC(int size); void FREE(void *ptr); #endif -#ifdef OUTTACACHE -int tobind(const char *iface_ip, int port); -int toconnect(const char *host, int port); -int toread(int fd, void *buf, int len); -int towrite(int fd, const void *buf, int len); -#endif #ifdef PLAY_ANGEL void pressanykey_or_callangel(void); #endif -#ifdef TIMET64 - struct tm *localtime4(const time4_t *); - time4_t time4(time4_t *); - char *ctime4(const time4_t *); -#else - #define localtime4(a) localtime(a) - #define time4(a) time(a) - #define ctime4(a) ctime(a) -#endif /* syspost */ int post_msg(const char* bname, const char* title, const char *msg, const char* author); @@ -811,7 +773,6 @@ int note(void); int Goodbye(void); /* toolkit */ -unsigned StringHash(const char *s); unsigned DBCS_StringHash(const char *s); /* passwd */ @@ -829,7 +790,6 @@ int freecuser(void); /* calendar */ int calendar(void); int ParseDate(const char *date, int *year, int *month, int *day); -int getHoroscope(int m, int d); /* util */ void touchbtotal(int bid); diff --git a/innbbsd/Makefile b/innbbsd/Makefile index 78d15673..3365e9c8 100644 --- a/innbbsd/Makefile +++ b/innbbsd/Makefile @@ -42,6 +42,8 @@ ${UTIL_DIR}/${fn}: # FIXME: dependency cd ${UTIL_DIR}; make ${fn} .endfor +LINK_UTIL_OBJS+= $(SRCROOT)/src/libbbsutil/libbbsutil.a \ + $(SRCROOT)/src/libbbs/libbbs.a echobbslib.o: echobbslib.c ${CC} ${CFLAGS} -DWITH_ECHOMAIL -c echobbslib.c diff --git a/mbbsd/Makefile b/mbbsd/Makefile index 327749b3..84468ffc 100644 --- a/mbbsd/Makefile +++ b/mbbsd/Makefile @@ -16,7 +16,7 @@ OBJS= admin.o announce.o args.o assess.o bbs.o board.o cache.o cal.o card.o\ more.o name.o osdep.o othello.o read.o record.o register.o\ screen.o stuff.o talk.o term.o topsong.o user.o brc.o vice.o vote.o\ xyz.o voteboard.o syspost.o var.o passwd.o calendar.o go.o file.o \ - pmore.o chess.o reversi.o + pmore.o chess.o reversi.o .if defined(DIET) OBJS+= random.o time.o alloc.o @@ -34,6 +34,8 @@ LDFLAGS+=-Wl,--sort-common CFLAGS+= -DMERGEBBS OBJS+= merge.o .endif +LIBS+= $(SRCROOT)/src/libbbsutil/libbbsutil.a \ + $(SRCROOT)/src/libbbs/libbbs.a .SUFFIXES: .c .o .c.o: $(SRCROOT)/include/var.h diff --git a/mbbsd/announce.c b/mbbsd/announce.c index bf6c8add..28ea9784 100644 --- a/mbbsd/announce.c +++ b/mbbsd/announce.c @@ -1179,8 +1179,7 @@ a_menu(const char *maintitle, const char *path, int lastlevel, char *trans_buffe strlcpy(trans_buffer, fname, PATHLEN); Fexit = 1; if (currstat == OSONG) { - log_file(FN_USSONG, LOG_CREAT | LOG_VF, - "%s\n", fhdr->title); + log_filef(FN_USSONG, LOG_CREAT, "%s\n", fhdr->title); } free(me.header); return FULLUPDATE; diff --git a/mbbsd/args.c b/mbbsd/args.c index 8d6ee98d..8a7658a7 100644 --- a/mbbsd/args.c +++ b/mbbsd/args.c @@ -10,9 +10,10 @@ initsetproctitle(int argc, char **argv, char **envp) #else -char **Argv = NULL; /* pointer to argument vector */ -char *LastArgv = NULL;/* end of argv */ -extern char **environ; +static char **Argv = NULL; /* pointer to argument vector */ +static int arg_size; /* end of argv */ + +extern char **environ; void initsetproctitle(int argc, char **argv, char **envp) @@ -20,6 +21,7 @@ initsetproctitle(int argc, char **argv, char **envp) register int i; int len=0,nenv=0; + /* * Move the environment so setproctitle can use the space at the top of * memory. @@ -40,9 +42,9 @@ initsetproctitle(int argc, char **argv, char **envp) /* Save start and extent of argv for setproctitle. */ Argv = argv; if (i > 0) - LastArgv = envp[i - 1] + strlen(envp[i - 1]); + argv_size = envp[i - 1] + strlen(envp[i - 1]) - Argv[0]; else - LastArgv = argv[argc - 1] + strlen(argv[argc - 1]); + argv_size = argv[argc - 1] + strlen(argv[argc - 1]) - Argv[0]; } static void @@ -51,9 +53,9 @@ do_setproctitle(const char *cmdline) int len; len = strlen(cmdline) + 1; // +1 for '\0' - if(len > LastArgv - Argv[0] - 2) // 2 ?? - len = LastArgv - Argv[0] - 2; - memset(Argv[0], 0, LastArgv-Argv[0]); + if(len > argv_size - 2) // 2 ?? + len = argv_size - 2; + memset(Argv[0], 0, argv_size); strlcpy(Argv[0], cmdline, len); Argv[1] = NULL; } diff --git a/mbbsd/bbs.c b/mbbsd/bbs.c index 55ddb14f..593efa07 100644 --- a/mbbsd/bbs.c +++ b/mbbsd/bbs.c @@ -85,7 +85,7 @@ static int currlistmode = LISTMODE_DATE; void anticrosspost(void) { - log_file("etc/illegal_money", LOG_CREAT | LOG_VF, + log_filef("etc/illegal_money", LOG_CREAT, ANSI_COLOR(1;33;46) "%s " ANSI_COLOR(37;45) "cross post 文章 " ANSI_COLOR(37) " %s" ANSI_RESET "\n", @@ -592,7 +592,7 @@ cancelpost(const fileheader_t *fh, int by_BM, char *newpath) fclose(fout); } fclose(fin); - log_file(fn1, LOG_CREAT | LOG_VF, "\n※ Deleted by: %s (%s) %d/%d", + log_filef(fn1, LOG_CREAT, "\n※ Deleted by: %s (%s) %d/%d", cuser.userid, fromhost, ptime->tm_mon + 1, ptime->tm_mday); Rename(fn1, newpath); setbdir(genbuf, brd); @@ -707,28 +707,6 @@ do_reply_title(int row, const char *title) // don't getdata() on non-local variable save_title directly, to avoid reentrant crash. strlcpy(save_title, tmp_title, sizeof(save_title)); } -/* -static void -do_unanonymous_post(const char *fpath) -{ - fileheader_t mhdr; - char title[128]; - char genbuf[200]; - - setbpath(genbuf, "UnAnonymous"); - if (dashd(genbuf)) { - stampfile(genbuf, &mhdr); - unlink(genbuf); - // XXX: Link should use BBSHOME/blah - Link(fpath, genbuf); - strlcpy(mhdr.owner, cuser.userid, sizeof(mhdr.owner)); - strlcpy(mhdr.title, save_title, sizeof(mhdr.title)); - mhdr.filemode = 0; - setbdir(title, "UnAnonymous"); - append_record(title, &mhdr, sizeof(mhdr)); - } -} -*/ void do_crosspost(const char *brd, fileheader_t *postfile, const char *fpath, @@ -3579,16 +3557,6 @@ change_counting(void) #endif -/** - * 改變目前所在板文章的預設儲存方式 - */ -static int -change_localsave(void) -{ - vmsg("此功\能已整合進大寫 I 看板設定,請按 I 設定。"); - return FULLUPDATE; -} - #ifdef USE_COOLDOWN int check_cooldown(boardheader_t *bp) @@ -3694,7 +3662,7 @@ const onekey_t read_comms[] = { { 0, NULL }, // Ctrl('U') { 0, do_post_vote }, // Ctrl('V') { 0, whereami }, // Ctrl('W') - { 0, change_localsave }, // Ctrl('X') + { 0, NULL }, // Ctrl('X') { 0, NULL }, // Ctrl('Y') { 1, push_bottom }, // Ctrl('Z') 26 { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, diff --git a/mbbsd/cal.c b/mbbsd/cal.c index d44b5b58..39f55514 100644 --- a/mbbsd/cal.c +++ b/mbbsd/cal.c @@ -58,24 +58,6 @@ unlockutmpmode(void) /* 使用錢的函數 */ #define VICE_NEW "vice.new" -const char* -money_level(int money) -{ - int i = 0; - - static const char *money_msg[] = - { - "債台高築", "赤貧", "清寒", "普通", "小康", - "小富", "中富", "大富翁", "富可敵國", "比爾蓋\天", NULL - }; - while (money_msg[i] && money > 10) - i++, money /= 10; - - if(!money_msg[i]) - i--; - return money_msg[i]; -} - /* Heat:發票 */ int vice(int money, const char *item) @@ -87,7 +69,7 @@ vice(int money, const char *item) if(money>=100) { setuserfile(buf, VICE_NEW); - log_file(buf, LOG_CREAT | LOG_VF, "%8.8d\n", viceserial); + log_filef(buf, LOG_CREAT, "%8.8d\n", viceserial); } snprintf(buf, sizeof(buf), "%s 花了$%d 編號[%08d]", item, money, viceserial); @@ -221,7 +203,7 @@ osong(void) fclose(fp1); fclose(fp); - log_file("etc/osong.log", LOG_CREAT | LOG_VF, "id: %-12s ◇ %s 點給 %s : \"%s\", 轉寄至 %s\n", cuser.userid, sender, receiver, say, address, ctime4(&now)); + log_filef("etc/osong.log", LOG_CREAT, "id: %-12s ◇ %s 點給 %s : \"%s\", 轉寄至 %s\n", cuser.userid, sender, receiver, say, address); if (append_record(OSONGPATH "/.DIR", &mail, sizeof(mail)) != -1) { cuser.lastsong = now; @@ -371,20 +353,6 @@ mail_redenvelop(const char *from, const char *to, int money, char mode) append_record(genbuf, &fhdr, sizeof(fhdr)); } -/* 計算贈與稅 */ -int -give_tax(int money) -{ - int i, tax = 0; - int tax_bound[] = {1000000, 100000, 10000, 1000, 0}; - double tax_rate[] = {0.4, 0.3, 0.2, 0.1, 0.08}; - for (i = 0; i <= 4; i++) - if (money > tax_bound[i]) { - tax += (money - tax_bound[i]) * tax_rate[i]; - money -= (money - tax_bound[i]); - } - return (tax <= 0) ? 1 : tax; -} int do_give_money(char *id, int uid, int money) { @@ -400,7 +368,7 @@ int do_give_money(char *id, int uid, int money) return -1; /* 繳完稅就沒錢給了 */ deumoney(uid, money - tax); demoney(-money); - log_file(FN_MONEY, LOG_CREAT | LOG_VF, "%-12s 給 %-12s %d\t(稅後 %d)\t%s", + log_filef(FN_MONEY, LOG_CREAT, "%-12s 給 %-12s %d\t(稅後 %d)\t%s", cuser.userid, id, money, money - tax, ctime4(&now)); #ifdef PLAY_ANGEL getuser(id, &xuser); diff --git a/mbbsd/calendar.c b/mbbsd/calendar.c index 865e52be..053474fe 100644 --- a/mbbsd/calendar.c +++ b/mbbsd/calendar.c @@ -1,8 +1,6 @@ /* $Id$ */ #include "bbs.h" -#if !defined(PTTBBS_UTIL) - typedef struct event_t { int year, month, day, days; int color; @@ -20,15 +18,6 @@ MonthDay(int m, int leap) } 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; @@ -37,7 +26,7 @@ Days(int y, int m, int d) + ((y - 1) / 4) - ((y - 1) / 100) + ((y - 1) / 400) + d - 1; for (i = 1; i < m; i++) - w += MonthDay(i, IsLeap(y)); + w += MonthDay(i, is_leap_year(y)); return w; } @@ -61,7 +50,7 @@ int ParseDate(const char *date, int *year, int *month, int *day) *month = atoi(m); *day = atoi(d); if (*year < 1 || *month < 1 || *month > 12 || - *day < 1 || *day > MonthDay(*month, IsLeap(*year))) + *day < 1 || *day > MonthDay(*month, is_leap_year(*year))) return 1; return 0; } @@ -242,7 +231,7 @@ GenerateCalendar(char **buf, int y, int m, int today, event_t * e) /* initial event */ for (; e && e->days < first_day; e = e->next); - d = MonthDay(m, IsLeap(y)); + d = MonthDay(m, is_leap_year(y)); for (i = 1; i <= d; i++, w = (w + 1) % 7) { attr1[0] = 0; attr2 = ""; @@ -336,25 +325,3 @@ calendar(void) pressanykey(); return 0; } - -#endif - -int getHoroscope(int m, int d) -{ - if (m > 12 || m < 1) - return 1; - - // Return: 1 .. 12 - // 摩羯 水瓶 雙魚 牡羊 金牛 雙子 巨蟹 獅子 處女 天秤 天蠍 射手 - const int firstday[12] = { - /* Jan. */ 20, 19, 21, 20, 21, 21, 23, 23, 23, 23, 22, 22 - }; - if (d >= firstday[m - 1]) { - if (m == 12) - return 1; - else - return m + 1; - } - else - return m; -} diff --git a/mbbsd/chicken.c b/mbbsd/chicken.c index 6fcffba3..7dd9118f 100644 --- a/mbbsd/chicken.c +++ b/mbbsd/chicken.c @@ -136,7 +136,7 @@ new_chicken(void) sizeof(tmp_name), DOECHO); strlcpy(mychicken->name, tmp_name, sizeof(mychicken->name)); - log_file(CHICKENLOG, LOG_CREAT | LOG_VF, + log_filef(CHICKENLOG, LOG_CREAT, ANSI_COLOR(31) "%s " ANSI_RESET "養了一隻叫" ANSI_COLOR(33) " %s " ANSI_RESET "的 " ANSI_COLOR(32) "%s" ANSI_RESET " 於 %s\n", cuser.userid, mychicken->name, chicken_type[(int)mychicken->type], ctime4(&now)); @@ -430,7 +430,7 @@ ch_kill(void) vice(100, "棄養寵物費"); more(CHICKEN_PIC "/deadth", YEA); - log_file(CHICKENLOG, LOG_CREAT | LOG_VF, + log_filef(CHICKENLOG, LOG_CREAT, ANSI_COLOR(31) "%s " ANSI_RESET "把 " ANSI_COLOR(33) "%s" ANSI_RESET ANSI_COLOR(32) " %s " ANSI_RESET "宰了 於 %s\n", cuser.userid, mychicken->name, chicken_type[(int)mychicken->type], ctime4(&now)); @@ -487,7 +487,7 @@ ch_sell(int age) ans = getans("這隻%d歲%s可以賣 %d 元, 是否要賣?(y/N)", age, chicken_type[(int)mychicken->type], money); if (ans == 'y') { - log_file(CHICKENLOG, LOG_CREAT | LOG_VF, + log_filef(CHICKENLOG, LOG_CREAT, ANSI_COLOR(31) "%s" ANSI_RESET " 把 " ANSI_COLOR(33) "%s" ANSI_RESET " " ANSI_COLOR(32) "%s" ANSI_RESET " 用 " ANSI_COLOR(36) "%d" ANSI_RESET " 賣了 於 %s\n", cuser.userid, mychicken->name, @@ -644,7 +644,7 @@ deadtype(const chicken_t * thechicken) return 0; if (thechicken == mychicken) { - log_file(CHICKENLOG, LOG_CREAT | LOG_VF, + log_filef(CHICKENLOG, LOG_CREAT, ANSI_COLOR(31) "%s" ANSI_RESET " 所疼愛的" ANSI_COLOR(33) " %s" ANSI_COLOR(32) " %s " ANSI_RESET "掛了 於 %s\n", cuser.userid, thechicken->name, chicken_type[(int)thechicken->type], ctime4(&now)); @@ -701,7 +701,7 @@ ch_changename(void) if (strlen(newname) >= 3 && strcmp(newname, mychicken->name)) { strlcpy(mychicken->name, newname, sizeof(mychicken->name)); - log_file(CHICKENLOG, LOG_CREAT | LOG_VF, + log_filef(CHICKENLOG, LOG_CREAT, ANSI_COLOR(31) "%s" ANSI_RESET " 把疼愛的" ANSI_COLOR(33) " %s" ANSI_COLOR(32) " %s " ANSI_RESET "改名為" ANSI_COLOR(33) " %s" ANSI_RESET " 於 %s\n", cuser.userid, mychicken->name, diff --git a/mbbsd/dice.c b/mbbsd/dice.c index e809044a..e353bec4 100644 --- a/mbbsd/dice.c +++ b/mbbsd/dice.c @@ -80,19 +80,6 @@ IsNum(const char *a, int n) return 1; } -#if 0 -static int -IsSNum(char *a) -{ - int i; - - for (i = 0; a[i]; i++) - if (a[i] > '9' || a[i] < '0') - return 0; - return 1; -} -#endif - static void show_data(void) { diff --git a/mbbsd/friend.c b/mbbsd/friend.c index e3c31fb9..a3e77f0d 100644 --- a/mbbsd/friend.c +++ b/mbbsd/friend.c @@ -319,7 +319,7 @@ inline void friend_load_real(int tosort, int maxf, fclose(fp); if( tosort ) - qsort(tarray, nFriends, sizeof(int), qsort_intcompar); + qsort(tarray, nFriends, sizeof(int), cmp_int); if( destn ) *destn = nFriends; tarray[nFriends] = 0; @@ -637,142 +637,6 @@ wait_input(float f, int flDoRefresh) return 1; } -/** - * 根據 mode 來 strip 字串 str,並把結果存到 buf - * @param buf - * @param str - * @param mode enum {STRIP_ALL = 0, ONLY_COLOR, NO_RELOAD}; - * STRIP_ALL: 全部吃掉 - * ONLY_COLOR: 吃掉所有跟顏色無關的 (ESC[*m) - * NO_RELOAD: 不 strip (?) - */ -static const char EscapeFlag[] = { - /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, - /* 20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, /* 0~9 ;= */ - /* 40 */ 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, /* ABCDHIJK */ - /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 60 */ 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 2, 0, 0, /* fhlm */ - /* 70 */ 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* su */ - /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* A0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* B0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* C0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* D0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* E0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; -#define isEscapeParam(X) (EscapeFlag[(int)(X)] & 1) -#define isEscapeCommand(X) (EscapeFlag[(int)(X)] & 2) - -int -strip_ansi(char *buf, const char *str, int mode) -{ - register int count = 0; - - for(; *str; ++str) - if( *str != ESC_CHR ){ - if( buf ) - *buf++ = *str; - ++count; - }else{ - const char* p = str + 1; - if( *p != '[' ){ - ++str; - if(*str=='\0') break; - continue; - } - while(isEscapeParam(*++p)); - if( (mode == NO_RELOAD && isEscapeCommand(*p)) || - (mode == ONLY_COLOR && *p == 'm' )){ - register int len = p - str + 1; - if( buf ){ - strncpy(buf, str, len); - buf += len; - } - count += len; - } - str = p; - if(*str=='\0') break; - } - if( buf ) - *buf = 0; - return count; -} - -int -strlen_noansi(const char *s) -{ - // XXX this is almost identical to - // strip_ansi(NULL, s, STRIP_ALL) - register int count = 0, mode = 0; - - if (!s || !*s) - return 0; - - for (; *s; ++s) - { - // 0 - no ansi, 1 - [, 2 - param+cmd - switch (mode) - { - case 0: - if (*s == ESC_CHR) - mode = 1; - else - count ++; - break; - - case 1: - if (*s == '[') - mode = 2; - else - mode = 0; // unknown command - break; - - case 2: - if (isEscapeParam(*s)) - continue; - else if (isEscapeCommand(*s)) - mode = 0; - else - mode = 0; - break; - } - } - return count; -} - -void -strip_nonebig5(unsigned char *str, int maxlen) -{ - int i; - int len=0; - for(i=0;i<maxlen && str[i];i++) { - if(32<=str[i] && str[i]<128) - str[len++]=str[i]; - else if(str[i]==255) { - if(i+1<maxlen) - if(251<=str[i+1] && str[i+1]<=254) { - i++; - if(i+1<maxlen && str[i+1]) - i++; - } - continue; - } else if(str[i]&0x80) { - if(i+1<maxlen) - if((0x40<=str[i+1] && str[i+1]<=0x7e) || - (0xa1<=str[i+1] && str[i+1]<=0xfe)) { - str[len++]=str[i]; - str[len++]=str[i+1]; - i++; - } - } - } - if(len<maxlen) - str[len]='\0'; -} #ifdef DBCSAWARE diff --git a/mbbsd/kaede.c b/mbbsd/kaede.c index 1dd8ba41..8e328e5d 100644 --- a/mbbsd/kaede.c +++ b/mbbsd/kaede.c @@ -71,108 +71,3 @@ Ptt_prints(char *str, size_t size, int mode) return str; } -int -Rename(const char *src, const char *dst) -{ - if (rename(src, dst) == 0) - return 0; - if (!strchr(src, ';') && !strchr(dst, ';')) - { - pid_t pid = fork(); - if (pid == 0) - execl("/bin/mv", "mv", "-f", src, dst, (char *)NULL); - else if (pid > 0) - waitpid(pid, NULL, 0); - else - return -1; - } - return 0; -} - -int -Copy(const char *src, const char *dst) -{ - int fi, fo, bytes; - char buf[8192]; - fi=open(src, O_RDONLY); - if(fi<0) return -1; - fo=open(dst, O_WRONLY | O_TRUNC | O_CREAT, 0600); - if(fo<0) {close(fi); return -1;} - while((bytes=read(fi, buf, sizeof(buf)))>0) - write(fo, buf, bytes); - close(fo); - close(fi); - return 0; -} - -int -CopyN(const char *src, const char *dst, int n) -{ - int fi, fo, bytes; - char buf[8192]; - - fi=open(src, O_RDONLY); - if(fi<0) return -1; - - fo=open(dst, O_WRONLY | O_TRUNC | O_CREAT, 0600); - if(fo<0) {close(fi); return -1;} - - while(n > 0 && (bytes=read(fi, buf, sizeof(buf)))>0) - { - n -= bytes; - if (n < 0) - bytes += n; - write(fo, buf, bytes); - } - close(fo); - close(fi); - return 0; -} - -/* append data from tail of src (starting point=off) to dst */ -int -AppendTail(const char *src, const char *dst, int off) -{ - int fi, fo, bytes; - char buf[8192]; - - fi=open(src, O_RDONLY); - if(fi<0) return -1; - - fo=open(dst, O_WRONLY | O_APPEND | O_CREAT, 0600); - if(fo<0) {close(fi); return -1;} - - if(off > 0) - lseek(fi, (off_t)off, SEEK_SET); - - while((bytes=read(fi, buf, sizeof(buf)))>0) - { - write(fo, buf, bytes); - } - close(fo); - close(fi); - return 0; -} - -int -Link(const char *src, const char *dst) -{ - if (strcmp(src, BBSHOME "/home") == 0) - return 1; - if (symlink(src, dst) == 0) - return 0; - - return Copy(src, dst); -} - -char * -my_ctime(const time4_t * t, char *ans, int len) -{ - struct tm *tp; - - tp = localtime4((time4_t*)t); - snprintf(ans, len, - "%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/mbbsd.c b/mbbsd/mbbsd.c index 87b98b0f..41a8ab4a 100644 --- a/mbbsd/mbbsd.c +++ b/mbbsd/mbbsd.c @@ -123,12 +123,12 @@ log_usies(const char *mode, const char *mesg) { now = time(NULL); if (!mesg) - log_file(FN_USIES, LOG_CREAT | LOG_VF, + log_filef(FN_USIES, LOG_CREAT, "%s %s %-12s Stay:%d (%s)\n", Cdate(&now), mode, cuser.userid , (int)(now - login_start_time) / 60, cuser.nickname); else - log_file(FN_USIES, LOG_CREAT | LOG_VF, + log_filef(FN_USIES, LOG_CREAT, "%s %s %-12s %s\n", Cdate(&now), mode, cuser.userid, mesg); @@ -277,7 +277,7 @@ abort_bbs_debug(int sig) /* log */ /* assume vsnprintf() in log_file() is signal-safe, is it? */ - log_file("log/crash.log", LOG_VF|LOG_CREAT, + log_filef("log/crash.log", LOG_CREAT, "%ld %d %d %.12s\n", time4(NULL), getpid(), sig, cuser.userid); /* try logout... not a good idea, maybe crash again. now disabled */ diff --git a/mbbsd/pmore.c b/mbbsd/pmore.c index 589fa893..abca918f 100644 --- a/mbbsd/pmore.c +++ b/mbbsd/pmore.c @@ -2295,7 +2295,7 @@ pmore(char *fpath, int promptend) #ifdef PMORE_LOG_SYSOP_EDIT time4_t t = time4(NULL); - log_file("log/security", LOG_VF|LOG_CREAT, + log_filef("log/security", LOG_CREAT, "%d %24.24s %d %s admin edit file=%s\n", t, ctime4(&t), getpid(), cuser.userid, fpath); #endif // PMORE_LOG_SYSOP_EDIT diff --git a/mbbsd/record.c b/mbbsd/record.c index d896398f..37d15870 100644 --- a/mbbsd/record.c +++ b/mbbsd/record.c @@ -5,21 +5,6 @@ #undef HAVE_MMAP #define BUFSIZE 512 -static void -PttLock(int fd, int start, int size, int mode) -{ - static struct flock lock_it; - int ret; - - lock_it.l_whence = SEEK_CUR;/* from current point */ - lock_it.l_start = start; /* -"- */ - 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) - sleep(1); -} - #define safewrite write int diff --git a/mbbsd/stuff.c b/mbbsd/stuff.c index 371583f4..abe65680 100644 --- a/mbbsd/stuff.c +++ b/mbbsd/stuff.c @@ -1,6 +1,5 @@ /* $Id$ */ #include "bbs.h" -#include "fnv_hash.h" /* ----------------------------------------------------- */ /* set file path for boards/user home */ @@ -9,7 +8,6 @@ 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 char cdate_buffer[32]; static const char * const str_dotdir = FN_DIR; @@ -127,81 +125,6 @@ subject(char *title) return title; } -/* ----------------------------------------------------- */ -/* 字串轉換檢查函數 */ -/* ----------------------------------------------------- */ -/** - * 將字串 s 轉為小寫存回 t - * @param t allocated char array - * @param s - */ -void -str_lower(char *t, const char *s) -{ - register unsigned char ch; - - do { - ch = *s++; - *t++ = char_lower(ch); - } while (ch); -} - -/** - * 移除字串 buf 後端多餘的空白。 - * @param buf - */ -void -trim(char *buf) -{ /* remove trailing space */ - char *p = buf; - - while (*p) - p++; - while (--p >= buf) { - if (*p == ' ') - *p = '\0'; - else - break; - } -} - -/** - * 移除 src 的 '\n' 並改成 '\0' - * @param src - */ -void chomp(char *src) -{ - while(*src){ - if (*src == '\n') - *src = 0; - else - src++; - } -} - -/* ----------------------------------------------------- */ -/* 字串檢查函數:英文、數字、檔名、E-mail address */ -/* ----------------------------------------------------- */ - -int -invalid_pname(const char *str) -{ - const 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)) /* 只允許 alnum 或這些符號 */ - return 1; - p1 = p2 + (*p2 ? 1 : 0); - } - return 0; -} - int is_validuserid(const char *id) { int len, i; @@ -212,10 +135,10 @@ int is_validuserid(const char *id) if (len < 2 || len>IDLEN) return 0; - if (not_alpha(id[0])) + if (!isalpha(id[0])) return 0; for (i = 1; i < len; i++) - if (not_alnum(id[i])) + if (!isalnum(id[i])) return 0; return 1; } @@ -279,197 +202,12 @@ userid_is_BM(const char *userid, const char *list) return 0; } -/* ----------------------------------------------------- */ -/* 檔案檢查函數:檔案、目錄、屬於 */ -/* ----------------------------------------------------- */ - -/** - * 傳回 fname 的檔案大小 - * @param fname - */ -off_t -dashs(const char *fname) -{ - struct stat st; - - if (!stat(fname, &st)) - return st.st_size; - else - return -1; -} - -/** - * 傳回 fname 的 mtime - * @param fname - */ -time4_t -dasht(const char *fname) -{ - struct stat st; - - if (!stat(fname, &st)) - return st.st_mtime; - else - return -1; -} - -/** - * 傳回 fname 是否為 symbolic link - * @param fname - */ -int -dashl(const char *fname) -{ - struct stat st; - - return (lstat(fname, &st) == 0 && S_ISLNK(st.st_mode)); -} - -/** - * 傳回 fname 是否為一般的檔案 - * @param fname - */ -int -dashf(const char *fname) -{ - struct stat st; - - return (stat(fname, &st) == 0 && S_ISREG(st.st_mode)); -} - -/** - * 傳回 fname 是否為目錄 - * @param fname - */ -int -dashd(const char *fname) -{ - struct stat st; - - return (stat(fname, &st) == 0 && S_ISDIR(st.st_mode)); -} - -#define BUFFER_SIZE 8192 -static int copy_file_to_file(const char *src, const char *dst) -{ - char buf[BUFFER_SIZE]; - int fdr, fdw, len; - - if ((fdr = open(src, O_RDONLY)) < 0) - return -1; - - if ((fdw = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { - close(fdr); - return -1; - } - - while (1) { - len = read(fdr, buf, sizeof(buf)); - if (len <= 0) - break; - write(fdw, buf, len); - if (len < BUFFER_SIZE) - break; - } - - close(fdr); - close(fdw); - return 0; -} -#undef BUFFER_SIZE - -static int copy_file_to_dir(const char *src, const char *dst) -{ - char buf[PATHLEN]; - char *slash; - if ((slash = rindex(src, '/')) == NULL) - snprintf(buf, PATHLEN, "%s/%s", dst, src); - else - snprintf(buf, PATHLEN, "%s/%s", dst, slash); - return copy_file_to_file(src, buf); -} - -static int copy_dir_to_dir(const char *src, const char *dst) -{ - DIR *dir; - struct dirent *entry; - struct stat st; - char buf[PATHLEN], buf2[PATHLEN]; - - if (stat(dst, &st) < 0) - if (mkdir(dst, 0700) < 0) - return -1; - - if ((dir = opendir(src)) == NULL) - return -1; - - while ((entry = readdir(dir)) != NULL) { - if (strcmp(entry->d_name, ".") == 0 || - strcmp(entry->d_name, "..") == 0) - continue; - snprintf(buf, PATHLEN, "%s/%s", src, entry->d_name); - snprintf(buf2, PATHLEN, "%s/%s", dst, entry->d_name); - if (stat(buf, &st) < 0) - continue; - if (S_ISDIR(st.st_mode)) - mkdir(buf2, 0700); - copy_file(buf, buf2); - } - - closedir(dir); - return 0; -} - -/** - * copy src to dst (recursively) - * @param src and dst are file or dir - * @return -1 if failed - */ -int copy_file(const char *src, const char *dst) -{ - struct stat st; - - if (stat(dst, &st) == 0 && S_ISDIR(st.st_mode)) { - if (stat(src, &st) < 0) - return -1; - - if (S_ISDIR(st.st_mode)) - return copy_dir_to_dir(src, dst); - else if (S_ISREG(st.st_mode)) - return copy_file_to_dir(src, dst); - return -1; - } - else if (stat(src, &st) == 0 && S_ISDIR(st.st_mode)) - return copy_dir_to_dir(src, dst); - return copy_file_to_file(src, dst); -} - int belong(const char *filelist, const char *key) { return file_exist_record(filelist, key); } -unsigned int -ipstr2int(const char *ip) -{ - unsigned int i, val = 0; - char buf[32]; - char *nil, *p; - - strlcpy(buf, ip, sizeof(buf)); - p = buf; - for (i = 0; i < 4; i++) { - nil = strchr(p, '.'); - if (nil != NULL) - *nil = 0; - val *= 256; - val += atoi(p); - if (nil != NULL) - p = nil + 1; - } - return val; -} #ifndef _BBS_UTIL_C_ /* getdata_buf */ time4_t @@ -502,35 +240,6 @@ gettime(int line, time4_t dt, const char*head) } #endif -char * -Cdate(const time4_t *clock) -{ - time_t temp = (time_t)*clock; - struct tm *mytm = localtime(&temp); - - strftime(cdate_buffer, sizeof(cdate_buffer), "%m/%d/%Y %T %a", mytm); - return cdate_buffer; -} - -char * -Cdatelite(const time4_t *clock) -{ - time_t temp = (time_t)*clock; - struct tm *mytm = localtime(&temp); - - strftime(cdate_buffer, sizeof(cdate_buffer), "%m/%d/%Y %T", mytm); - return cdate_buffer; -} - -char * -Cdatedate(const time4_t * clock) -{ - time_t temp = (time_t)*clock; - struct tm *mytm = localtime(&temp); - - strftime(cdate_buffer, sizeof(cdate_buffer), "%m/%d/%Y", mytm); - return cdate_buffer; -} #ifndef _BBS_UTIL_C_ /* 這一區都是有關於畫面處理的, 故 _BBS_UTIL_C_ 不須要 */ @@ -858,36 +567,7 @@ log_user(const char *fmt, ...) va_end(ap); sethomefile(filename, cuser.userid, "USERLOG"); - return log_file(filename, LOG_CREAT | LOG_VF, - "%s: %s %s", cuser.userid, msg, Cdate(&now)); -} - -int -log_file(const char *fn, int flag, const char *fmt,...) -{ - int fd; - char msg[256]; - const char *realmsg; - if( !(flag & LOG_VF) ){ - realmsg = fmt; - } - else{ - va_list ap; - va_start(ap, fmt); - vsnprintf(msg , 128, fmt, ap); - va_end(ap); - realmsg = msg; - } - - if( (fd = open(fn, O_APPEND | O_WRONLY | ((flag & LOG_CREAT)? O_CREAT : 0), - ((flag & LOG_CREAT) ? 0664 : 0))) < 0 ) - return -1; - if( write(fd, realmsg, strlen(realmsg)) < 0 ){ - close(fd); - return -1; - } - close(fd); - return 0; + return log_filef(filename, LOG_CREAT, "%s: %s %s", cuser.userid, msg, Cdate(&now)); } void @@ -954,11 +634,6 @@ void FREE(void *ptr) } #endif -unsigned -StringHash(const char *s) -{ - return fnv1a_32_strcase(s, FNV1_32_INIT); -} unsigned DBCS_StringHash(const char *s) @@ -1007,120 +682,3 @@ uintbsearch(const unsigned int key, const unsigned int *base0, const int nmemb) return (NULL); } -int qsort_intcompar(const void *a, const void *b) -{ - return *(int *)a - *(int *)b; -} - -#ifdef TIMET64 -char * -ctime4(const time4_t *clock) -{ - time_t temp = (time_t)*clock; - - return ctime(&temp); -} - -struct tm *localtime4(const time4_t *t) -{ - if( t == NULL ) - return localtime(NULL); - else { - time_t temp = (time_t)*t; - return localtime(&temp); - } -} - -time4_t time4(time4_t *ptr) -{ - if( ptr == NULL ) - return time(NULL); - else - return *ptr = (time4_t)time(NULL); -} -#endif - -#ifdef OUTTACACHE -int tobind(const char * host, int port) -{ - int sockfd, val = 1; - struct sockaddr_in servaddr; - - if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { - perror("socket()"); - exit(1); - } - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, - (char *)&val, sizeof(val)); - bzero(&servaddr, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - if (host == NULL || host[0] == 0) - servaddr.sin_addr.s_addr = htonl(INADDR_ANY); - else if (inet_aton(host, &servaddr.sin_addr) == 0) { - perror("inet_aton()"); - exit(1); - } - servaddr.sin_port = htons(port); - if( bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) { - perror("bind()"); - exit(1); - } - if( listen(sockfd, 5) < 0 ) { - perror("listen()"); - exit(1); - } - - return sockfd; -} - -int toconnect(const char *host, int port) -{ - int sock; - struct sockaddr_in serv_name; - if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ - perror("socket"); - return -1; - } - - serv_name.sin_family = AF_INET; - serv_name.sin_addr.s_addr = inet_addr(host); - serv_name.sin_port = htons(port); - if( connect(sock, (struct sockaddr*)&serv_name, sizeof(serv_name)) < 0 ){ - close(sock); - return -1; - } - return sock; -} - -/** - * same as read(2), but read until exactly size len - */ -int toread(int fd, void *buf, int len) -{ - int l; - for( l = 0 ; len > 0 ; ) - if( (l = read(fd, buf, len)) <= 0 ) - return -1; - else{ - buf += l; - len -= l; - } - return l; -} - -/** - * same as write(2), but write until exactly size len - */ -int towrite(int fd, const void *buf, int len) -{ - int l; - for( l = 0 ; len > 0 ; ) - if( (l = write(fd, buf, len)) <= 0 ) - return -1; - else{ - buf += l; - len -= l; - } - return l; -} -#endif diff --git a/mbbsd/topsong.c b/mbbsd/topsong.c index a60a26c4..906dadbf 100644 --- a/mbbsd/topsong.c +++ b/mbbsd/topsong.c @@ -25,15 +25,6 @@ topsong(void) return 0; } -static int -strip_blank(char *cbuf, char *buf) -{ - for (; *buf; buf++) - if (*buf != ' ') - *cbuf++ = *buf; - *cbuf = 0; - return 0; -} void sortsong(void) diff --git a/mbbsd/user.c b/mbbsd/user.c index 889bc9b0..f2475e95 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -100,7 +100,7 @@ int u_cancelbadpost(void) cuser.badpost--; cuser.timeremovebadpost = now; passwd_update(usernum, &cuser); - log_file("log/cancelbadpost.log", LOG_VF|LOG_CREAT, + log_filef("log/cancelbadpost.log", LOG_CREAT, "%s %s 刪除一篇劣文\n", Cdate(&now), cuser.userid); } vmsg("恭喜您已經成功\刪除一篇劣文."); diff --git a/src/libbbs/Makefile b/src/libbbs/Makefile new file mode 100644 index 00000000..efbf9534 --- /dev/null +++ b/src/libbbs/Makefile @@ -0,0 +1,20 @@ + +SRCROOT= ../.. +.include "$(SRCROOT)/pttbbs.mk" + +CFLAGS+= -I$(SRCROOT)/include + +OBJS= log.o string.o money.o +TARGET= libbbs.a + + +.SUFFIXES: .c .o +.c.o: + $(CCACHE) $(DIETCC) $(CC) $(CFLAGS) -c $*.c + +$(TARGET): $(OBJS) + $(AR) cru $@ $(OBJS) + ranlib $@ + +clean: + rm -f $(OBJS) $(TARGET) diff --git a/src/libbbs/log.c b/src/libbbs/log.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/libbbs/log.c diff --git a/src/libbbs/money.c b/src/libbbs/money.c new file mode 100644 index 00000000..a6d54127 --- /dev/null +++ b/src/libbbs/money.c @@ -0,0 +1,37 @@ +#include <stdio.h> + +#include <libbbs.h> + +/* 計算贈與稅 */ +int +give_tax(int money) +{ + int i, tax = 0; + int tax_bound[] = {1000000, 100000, 10000, 1000, 0}; + double tax_rate[] = {0.4, 0.3, 0.2, 0.1, 0.08}; + for (i = 0; i <= 4; i++) + if (money > tax_bound[i]) { + tax += (money - tax_bound[i]) * tax_rate[i]; + money -= (money - tax_bound[i]); + } + return (tax <= 0) ? 1 : tax; +} + +const char* +money_level(int money) +{ + int i = 0; + + static const char *money_msg[] = + { + "債台高築", "赤貧", "清寒", "普通", "小康", + "小富", "中富", "大富翁", "富可敵國", "比爾蓋\天", NULL + }; + while (money_msg[i] && money > 10) + i++, money /= 10; + + if(!money_msg[i]) + i--; + return money_msg[i]; +} + diff --git a/src/libbbs/string.c b/src/libbbs/string.c new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/libbbs/string.c @@ -0,0 +1 @@ + diff --git a/src/libbbsutil/Makefile b/src/libbbsutil/Makefile new file mode 100644 index 00000000..eafe2ab5 --- /dev/null +++ b/src/libbbsutil/Makefile @@ -0,0 +1,20 @@ + +SRCROOT= ../.. +.include "$(SRCROOT)/pttbbs.mk" + +CFLAGS+= -I$(SRCROOT)/include + +OBJS= file.o lock.o log.o net.o sort.o string.o time.o +TARGET= libbbsutil.a + + +.SUFFIXES: .c .o +.c.o: + $(CCACHE) $(DIETCC) $(CC) $(CFLAGS) -c $*.c + +$(TARGET): $(OBJS) + $(AR) cru $@ $(OBJS) + ranlib $@ + +clean: + rm -f $(OBJS) $(TARGET) diff --git a/src/libbbsutil/file.c b/src/libbbsutil/file.c new file mode 100644 index 00000000..c508e2de --- /dev/null +++ b/src/libbbsutil/file.c @@ -0,0 +1,276 @@ +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <limits.h> +#include <strings.h> +#include <dirent.h> +#include <string.h> +#include <sys/wait.h> + +#include "libbbsutil.h" + + +/* ----------------------------------------------------- */ +/* 檔案檢查函數:檔案、目錄、屬於 */ +/* ----------------------------------------------------- */ + +/** + * 傳回 fname 的檔案大小 + * @param fname + */ +off_t +dashs(const char *fname) +{ + struct stat st; + + if (!stat(fname, &st)) + return st.st_size; + else + return -1; +} + +/** + * 傳回 fname 的 mtime + * @param fname + */ +time4_t +dasht(const char *fname) +{ + struct stat st; + + if (!stat(fname, &st)) + return st.st_mtime; + else + return -1; +} + +/** + * 傳回 fname 是否為 symbolic link + * @param fname + */ +int +dashl(const char *fname) +{ + struct stat st; + + return (lstat(fname, &st) == 0 && S_ISLNK(st.st_mode)); +} + +/** + * 傳回 fname 是否為一般的檔案 + * @param fname + */ +int +dashf(const char *fname) +{ + struct stat st; + + return (stat(fname, &st) == 0 && S_ISREG(st.st_mode)); +} + +/** + * 傳回 fname 是否為目錄 + * @param fname + */ +int +dashd(const char *fname) +{ + struct stat st; + + return (stat(fname, &st) == 0 && S_ISDIR(st.st_mode)); +} + +#define BUFFER_SIZE 8192 +int copy_file_to_file(const char *src, const char *dst) +{ + char buf[BUFFER_SIZE]; + int fdr, fdw, len; + + if ((fdr = open(src, O_RDONLY)) < 0) + return -1; + + if ((fdw = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { + close(fdr); + return -1; + } + + while (1) { + len = read(fdr, buf, sizeof(buf)); + if (len <= 0) + break; + write(fdw, buf, len); + if (len < BUFFER_SIZE) + break; + } + + close(fdr); + close(fdw); + return 0; +} +#undef BUFFER_SIZE + +int copy_file_to_dir(const char *src, const char *dst) +{ + char buf[PATH_MAX]; + char *slash; + if ((slash = rindex(src, '/')) == NULL) + snprintf(buf, sizeof(buf), "%s/%s", dst, src); + else + snprintf(buf, sizeof(buf), "%s/%s", dst, slash); + return copy_file_to_file(src, buf); +} + +int copy_dir_to_dir(const char *src, const char *dst) +{ + DIR *dir; + struct dirent *entry; + struct stat st; + char buf[PATH_MAX], buf2[PATH_MAX]; + + if (stat(dst, &st) < 0) + if (mkdir(dst, 0700) < 0) + return -1; + + if ((dir = opendir(src)) == NULL) + return -1; + + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) + continue; + snprintf(buf, sizeof(buf), "%s/%s", src, entry->d_name); + snprintf(buf2, sizeof(buf2), "%s/%s", dst, entry->d_name); + if (stat(buf, &st) < 0) + continue; + if (S_ISDIR(st.st_mode)) + mkdir(buf2, 0700); + copy_file(buf, buf2); + } + + closedir(dir); + return 0; +} + +/** + * copy src to dst (recursively) + * @param src and dst are file or dir + * @return -1 if failed + */ +int copy_file(const char *src, const char *dst) +{ + struct stat st; + + if (stat(dst, &st) == 0 && S_ISDIR(st.st_mode)) { + if (stat(src, &st) < 0) + return -1; + + if (S_ISDIR(st.st_mode)) + return copy_dir_to_dir(src, dst); + else if (S_ISREG(st.st_mode)) + return copy_file_to_dir(src, dst); + return -1; + } + else if (stat(src, &st) == 0 && S_ISDIR(st.st_mode)) + return copy_dir_to_dir(src, dst); + return copy_file_to_file(src, dst); +} + +int +Rename(const char *src, const char *dst) +{ + if (rename(src, dst) == 0) + return 0; + if (!strchr(src, ';') && !strchr(dst, ';')) + { + pid_t pid = fork(); + if (pid == 0) + execl("/bin/mv", "mv", "-f", src, dst, (char *)NULL); + else if (pid > 0) + waitpid(pid, NULL, 0); + else + return -1; + } + return -1; +} + +int +Copy(const char *src, const char *dst) +{ + int fi, fo, bytes; + char buf[8192]; + fi=open(src, O_RDONLY); + if(fi<0) return -1; + fo=open(dst, O_WRONLY | O_TRUNC | O_CREAT, 0600); + if(fo<0) {close(fi); return -1;} + while((bytes=read(fi, buf, sizeof(buf)))>0) + write(fo, buf, bytes); + close(fo); + close(fi); + return 0; +} + +int +CopyN(const char *src, const char *dst, int n) +{ + int fi, fo, bytes; + char buf[8192]; + + fi=open(src, O_RDONLY); + if(fi<0) return -1; + + fo=open(dst, O_WRONLY | O_TRUNC | O_CREAT, 0600); + if(fo<0) {close(fi); return -1;} + + while(n > 0 && (bytes=read(fi, buf, sizeof(buf)))>0) + { + n -= bytes; + if (n < 0) + bytes += n; + write(fo, buf, bytes); + } + close(fo); + close(fi); + return 0; +} + +/* append data from tail of src (starting point=off) to dst */ +int +AppendTail(const char *src, const char *dst, int off) +{ + int fi, fo, bytes; + char buf[8192]; + + fi=open(src, O_RDONLY); + if(fi<0) return -1; + + fo=open(dst, O_WRONLY | O_APPEND | O_CREAT, 0600); + if(fo<0) {close(fi); return -1;} + + if(off > 0) + lseek(fi, (off_t)off, SEEK_SET); + + while((bytes=read(fi, buf, sizeof(buf)))>0) + { + write(fo, buf, bytes); + } + close(fo); + close(fi); + return 0; +} + +/** + * @param src file + * @param dst file + * @return 0 if success + */ +int +Link(const char *src, const char *dst) +{ + if (symlink(src, dst) == 0) + return 0; + + return Copy(src, dst); +} + diff --git a/src/libbbsutil/lock.c b/src/libbbsutil/lock.c new file mode 100644 index 00000000..4b28bab1 --- /dev/null +++ b/src/libbbsutil/lock.c @@ -0,0 +1,23 @@ +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +/** + * lock fd + * @param mode F_WRLCK, F_UNLCK + */ +void +PttLock(int fd, int start, int size, int mode) +{ + static struct flock lock_it; + int ret; + + lock_it.l_whence = SEEK_CUR;/* from current point */ + lock_it.l_start = start; /* -"- */ + 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) + sleep(1); +} + diff --git a/src/libbbsutil/log.c b/src/libbbsutil/log.c new file mode 100644 index 00000000..9fe3d514 --- /dev/null +++ b/src/libbbsutil/log.c @@ -0,0 +1,43 @@ +#include <stdarg.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> + +#include "libbbsutil.h" + +int +log_filef(const char *fn, int log_flag, const char *fmt,...) +{ + char msg[256]; + + va_list ap; + va_start(ap, fmt); + vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + + return log_file(fn, log_flag, msg); +} + +int +log_file(const char *fn, int log_flag, const char *msg) +{ + int fd; + int flag = O_APPEND | O_WRONLY; + int mode = 0664; + + if (log_flag & LOG_CREAT) + flag |= O_CREAT; + + fd = open(fn, flag, mode); + if( fd < 0 ) + return -1; + + if( write(fd, msg, strlen(msg)) < 0 ){ + close(fd); + return -1; + } + close(fd); + return 0; +} + diff --git a/src/libbbsutil/net.c b/src/libbbsutil/net.c new file mode 100644 index 00000000..60208a65 --- /dev/null +++ b/src/libbbsutil/net.c @@ -0,0 +1,114 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> + +#include "libbbsutil.h" + +unsigned int +ipstr2int(const char *ip) +{ + unsigned int i, val = 0; + char buf[32]; + char *nil, *p; + + strlcpy(buf, ip, sizeof(buf)); + p = buf; + for (i = 0; i < 4; i++) { + nil = strchr(p, '.'); + if (nil != NULL) + *nil = 0; + val *= 256; + val += atoi(p); + if (nil != NULL) + p = nil + 1; + } + return val; +} + +int tobind(const char * host, int port) +{ + int sockfd, val = 1; + struct sockaddr_in servaddr; + + if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { + perror("socket()"); + exit(1); + } + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&val, sizeof(val)); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + if (host == NULL || host[0] == 0) + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + else if (inet_aton(host, &servaddr.sin_addr) == 0) { + perror("inet_aton()"); + exit(1); + } + servaddr.sin_port = htons(port); + if( bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) { + perror("bind()"); + exit(1); + } + if( listen(sockfd, 5) < 0 ) { + perror("listen()"); + exit(1); + } + + return sockfd; +} + +int toconnect(const char *host, int port) +{ + int sock; + struct sockaddr_in serv_name; + if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ + perror("socket"); + return -1; + } + + serv_name.sin_family = AF_INET; + serv_name.sin_addr.s_addr = inet_addr(host); + serv_name.sin_port = htons(port); + if( connect(sock, (struct sockaddr*)&serv_name, sizeof(serv_name)) < 0 ){ + close(sock); + return -1; + } + return sock; +} + +/** + * same as read(2), but read until exactly size len + */ +int toread(int fd, void *buf, int len) +{ + int l; + for( l = 0 ; len > 0 ; ) + if( (l = read(fd, buf, len)) <= 0 ) + return -1; + else{ + buf += l; + len -= l; + } + return l; +} + +/** + * same as write(2), but write until exactly size len + */ +int towrite(int fd, const void *buf, int len) +{ + int l; + for( l = 0 ; len > 0 ; ) + if( (l = write(fd, buf, len)) <= 0 ) + return -1; + else{ + buf += l; + len -= l; + } + return l; +} diff --git a/src/libbbsutil/sort.c b/src/libbbsutil/sort.c new file mode 100644 index 00000000..edecc0a8 --- /dev/null +++ b/src/libbbsutil/sort.c @@ -0,0 +1,10 @@ + +int cmp_int(const void *a, const void *b) +{ + return *(int*)a - *(int*)b; +} + +int cmp_int_desc(const void * a, const void * b) +{ + return cmp_int(b, a); +} diff --git a/src/libbbsutil/string.c b/src/libbbsutil/string.c new file mode 100644 index 00000000..695d65ab --- /dev/null +++ b/src/libbbsutil/string.c @@ -0,0 +1,284 @@ +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include "fnv_hash.h" + +#include "ansi.h" +#include "libbbsutil.h" + +#define CHAR_LOWER(c) ((c >= 'A' && c <= 'Z') ? c|32 : c) +/* ----------------------------------------------------- */ +/* 字串轉換檢查函數 */ +/* ----------------------------------------------------- */ +/** + * 將字串 s 轉為小寫存回 t + * @param t allocated char array + * @param s + */ +void +str_lower(char *t, const char *s) +{ + register unsigned char ch; + + do { + ch = *s++; + *t++ = CHAR_LOWER(ch); + } while (ch); +} + +/** + * 移除字串 buf 後端多餘的空白。 + * @param buf + */ +void +trim(char *buf) +{ /* remove trailing space */ + char *p = buf; + + while (*p) + p++; + while (--p >= buf) { + if (*p == ' ') + *p = '\0'; + else + break; + } +} + +/** + * 移除 src 的 '\n' 並改成 '\0' + * @param src + */ +void chomp(char *src) +{ + while(*src){ + if (*src == '\n') + *src = 0; + else + src++; + } +} + +int +strip_blank(char *cbuf, char *buf) +{ + for (; *buf; buf++) + if (*buf != ' ') + *cbuf++ = *buf; + *cbuf = 0; + return 0; +} + +static const char EscapeFlag[] = { + /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, + /* 20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 30 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, /* 0~9 ;= */ + /* 40 */ 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, /* ABCDHIJK */ + /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 60 */ 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 2, 0, 0, /* fhlm */ + /* 70 */ 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* su */ + /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* A0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* B0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* C0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* D0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* E0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +/** + * 根據 mode 來 strip 字串 src,並把結果存到 dst + * @param dst + * @param src + * @param mode enum {STRIP_ALL = 0, ONLY_COLOR, NO_RELOAD}; + * STRIP_ALL: 全部吃掉 + * ONLY_COLOR: 吃掉所有跟顏色無關的 (ESC[*m) + * NO_RELOAD: 不 strip (?) + * @return strip 後的長度 + */ +int +strip_ansi(char *dst, const char *src, enum STRIP_FLAG mode) +{ + register int count = 0; +#define isEscapeParam(X) (EscapeFlag[(int)(X)] & 1) +#define isEscapeCommand(X) (EscapeFlag[(int)(X)] & 2) + + for(; *src; ++src) + if( *src != ESC_CHR ){ + if( dst ) + *dst++ = *src; + ++count; + }else{ + const char* p = src + 1; + if( *p != '[' ){ + ++src; + if(*src=='\0') break; + continue; + } + while(isEscapeParam(*++p)); + if( (mode == NO_RELOAD && isEscapeCommand(*p)) || + (mode == ONLY_COLOR && *p == 'm' )){ + register int len = p - src + 1; + if( dst ){ + strncpy(dst, src, len); + dst += len; + } + count += len; + } + src = p; + if(*src=='\0') break; + } + if( dst ) + *dst = 0; + return count; +} + +int +strlen_noansi(const char *s) +{ + // XXX this is almost identical to + // strip_ansi(NULL, s, STRIP_ALL) + register int count = 0, mode = 0; + + if (!s || !*s) + return 0; + + for (; *s; ++s) + { + // 0 - no ansi, 1 - [, 2 - param+cmd + switch (mode) + { + case 0: + if (*s == ESC_CHR) + mode = 1; + else + count ++; + break; + + case 1: + if (*s == '[') + mode = 2; + else + mode = 0; // unknown command + break; + + case 2: + if (isEscapeParam(*s)) + continue; + else if (isEscapeCommand(*s)) + mode = 0; + else + mode = 0; + break; + } + } + return count; +} + +void +strip_nonebig5(unsigned char *str, int maxlen) +{ + int i; + int len=0; + for(i=0;i<maxlen && str[i];i++) { + if(32<=str[i] && str[i]<128) + str[len++]=str[i]; + else if(str[i]==255) { + if(i+1<maxlen) + if(251<=str[i+1] && str[i+1]<=254) { + i++; + if(i+1<maxlen && str[i+1]) + i++; + } + continue; + } else if(str[i]&0x80) { + if(i+1<maxlen) + if((0x40<=str[i+1] && str[i+1]<=0x7e) || + (0xa1<=str[i+1] && str[i+1]<=0xfe)) { + str[len++]=str[i]; + str[len++]=str[i+1]; + i++; + } + } + } + if(len<maxlen) + str[len]='\0'; +} + +/* ----------------------------------------------------- */ +/* 字串檢查函數:英文、數字、檔名、E-mail address */ +/* ----------------------------------------------------- */ + +int +invalid_pname(const char *str) +{ + const 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 (!isalnum(*p3) && !strchr("@[]-._", *p3)) /* 只允許 alnum 或這些符號 */ + return 1; + p1 = p2 + (*p2 ? 1 : 0); + } + return 0; +} + +/* + * return 1 if /^[0-9]+$/ + * 0 else, 含空字串 + */ +int is_number(const char *p) +{ + if (*p == '\0') + return 0; + + for(; *p; p++) { + if (*p < '0' || '9' < *p) + return 0; + } + return 1; +} + +unsigned +StringHash(const char *s) +{ + return fnv1a_32_strcase(s, FNV1_32_INIT); +} + +/* qp_encode() modified from mutt-1.5.7/rfc2047.c q_encoder() */ +const char MimeSpecials[] = "@.,;:<>[]\\\"()?/= \t"; +char * qp_encode (char *s, size_t slen, const char *d, const char *tocode) +{ + char hex[] = "0123456789ABCDEF"; + char *s0 = s; + + memcpy (s, "=?", 2), s += 2; + memcpy (s, tocode, strlen (tocode)), s += strlen (tocode); + memcpy (s, "?Q?", 3), s += 3; + assert(s-s0+3<slen); + + while (*d != '\0' && s-s0+6<slen) + { + unsigned char c = *d++; + if (c == ' ') + *s++ = '_'; + else if (c >= 0x7f || c < 0x20 || c == '_' || strchr (MimeSpecials, c)) + { + *s++ = '='; + *s++ = hex[(c & 0xf0) >> 4]; + *s++ = hex[c & 0x0f]; + } + else + *s++ = c; + } + memcpy (s, "?=", 2), s += 2; + *s='\0'; + return s0; +} + diff --git a/src/libbbsutil/time.c b/src/libbbsutil/time.c new file mode 100644 index 00000000..2e0dbdd1 --- /dev/null +++ b/src/libbbsutil/time.c @@ -0,0 +1,116 @@ +#include <time.h> +#include <stdio.h> +#include "libbbsutil.h" + +static char cdate_buffer[32]; + +/** + * 閏年 + */ +int is_leap_year(int year) +{ + return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); +} + +/** + * 給日期求星座 + * + * @return 1..12 + */ +int getHoroscope(int m, int d) +{ + if (m > 12 || m < 1) + return 1; + + // 摩羯 水瓶 雙魚 牡羊 金牛 雙子 巨蟹 獅子 處女 天秤 天蠍 射手 + const int firstday[12] = { + /* Jan. */ 20, 19, 21, 20, 21, 21, 23, 23, 23, 23, 22, 22 + }; + if (d >= firstday[m - 1]) { + if (m == 12) + return 1; + else + return m + 1; + } + else + return m; +} + +/** + * 23+1 bytes, "12/31/2007 00:00:00 Mon\0" + */ +char * +Cdate(const time4_t *clock) +{ + time_t temp = (time_t)*clock; + struct tm *mytm = localtime(&temp); + + strftime(cdate_buffer, sizeof(cdate_buffer), "%m/%d/%Y %T %a", mytm); + return cdate_buffer; +} + +/** + * 19+1 bytes, "12/31/2007 00:00:00\0" + */ +char * +Cdatelite(const time4_t *clock) +{ + time_t temp = (time_t)*clock; + struct tm *mytm = localtime(&temp); + + strftime(cdate_buffer, sizeof(cdate_buffer), "%m/%d/%Y %T", mytm); + return cdate_buffer; +} + +/** + * 10+1 bytes, "12/31/2007\0" + */ +char * +Cdatedate(const time4_t * clock) +{ + time_t temp = (time_t)*clock; + struct tm *mytm = localtime(&temp); + + strftime(cdate_buffer, sizeof(cdate_buffer), "%m/%d/%Y", mytm); + return cdate_buffer; +} + +#ifdef TIMET64 +char * +ctime4(const time4_t *clock) +{ + time_t temp = (time_t)*clock; + + return ctime(&temp); +} + +struct tm *localtime4(const time4_t *t) +{ + if( t == NULL ) + return localtime(NULL); + else { + time_t temp = (time_t)*t; + return localtime(&temp); + } +} + +time4_t time4(time4_t *ptr) +{ + if( ptr == NULL ) + return time(NULL); + else + return *ptr = (time4_t)time(NULL); +} +#endif + +char * +my_ctime(const time4_t * t, char *ans, int len) +{ + struct tm *tp; + + tp = localtime4((time4_t*)t); + snprintf(ans, len, + "%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/util/BM_money.c b/util/BM_money.c index 1f5cc10f..b089fb0b 100644 --- a/util/BM_money.c +++ b/util/BM_money.c @@ -15,17 +15,6 @@ int c, n; -int Link(const char *src, const char *dst) { - char cmd[200]; - - if (link(src, dst) == 0) - return 0; - - sprintf(cmd, "/bin/cp -R %s %s", src, dst); - return system(cmd); -} - - int main(int argc, char **argv) { FILE *fp = fopen(BBSHOME "/etc/topboardman", "r"); diff --git a/util/Makefile b/util/Makefile index ca7b0fd0..48fadad8 100644 --- a/util/Makefile +++ b/util/Makefile @@ -10,7 +10,7 @@ BBSBASE= $(SRCROOT)/include/var.h UTIL_OBJS= \ util_cache.o util_record.o util_passwd.o util_var.o \ util_stuff.o util_osdep.o util_args.o util_file.o \ - util_crypt.o util_calendar.o + util_crypt.o MBBSD_OBJS= \ cache record passwd var \ @@ -27,11 +27,12 @@ CPROG_WITH_UTIL= \ reaper buildAnnounce inndBM mailangel \ outmail chkhbf merge_dir \ transman angel gamblegive wretch_man \ - chesscountry tunepasswd buildir xchatd + chesscountry tunepasswd buildir xchatd \ + uhash_loader # 下面這些程式, 會直接被 compile CPROG_WITHOUT_UTIL= \ - uhash_loader showboard countalldice bbsrf \ + showboard countalldice bbsrf \ initbbs userlist merge_board bbsmail # 下面這些程式會被 install @@ -43,6 +44,10 @@ PROGS= ${CPROG_WITH_UTIL} ${CPROG_WITHOUT_UTIL} \ dailybackup.pl tarqueue.pl waterball.pl filtermail.pl \ getbackup.pl udnnews.pl rebuildaloha.pl +LIBS+= $(SRCROOT)/src/libbbsutil/libbbsutil.a \ + $(SRCROOT)/src/libbbs/libbbs.a + + all: ${CPROG_WITH_UTIL} ${CPROG_WITHOUT_UTIL} ${PROGS} $(SRCROOT)/include/var.h: $(SRCROOT)/mbbsd/var.c @@ -50,7 +55,7 @@ $(SRCROOT)/include/var.h: $(SRCROOT)/mbbsd/var.c .for fn in ${CPROG_WITH_UTIL} ${fn}: ${BBSBASE} ${fn}.c ${UTIL_OBJS} - $(CCACHE) ${CC} ${CFLAGS} ${LDFLAGS} -o ${fn} ${UTIL_OBJS} ${fn}.c + $(CCACHE) ${CC} ${CFLAGS} ${LDFLAGS} -o ${fn} ${UTIL_OBJS} ${fn}.c $(LIBS) .endfor .for fn in ${MBBSD_OBJS} @@ -59,7 +64,7 @@ util_${fn}.o: ${BBSBASE} $(SRCROOT)/mbbsd/${fn}.c .endfor shmctl: ${BBSBASE} shmctl.c ${UTIL_OBJS} - $(CCACHE) ${CXX} ${CFLAGS} ${LDFLAGS} -o shmctl ${UTIL_OBJS} shmctl.c + $(CCACHE) ${CXX} ${CFLAGS} ${LDFLAGS} -o shmctl ${UTIL_OBJS} shmctl.c $(LIBS) #shmctl: ${BBSBASE} shmctl.c ${UTIL_OBJS} # $(CCACHE) gcc -g -DBBSHOME='"/home/bbs"' -I$(SRCROOT)/include -D__OS_MAJOR_VERSION__="2" -D__OS_MINOR_VERSION__="6" -DPTTBBS_UTIL -O1 -o shmctl ${UTIL_OBJS} shmctl.c #shmctl: ${BBSBASE} shmctl.cc ${UTIL_OBJS} @@ -67,7 +72,7 @@ shmctl: ${BBSBASE} shmctl.c ${UTIL_OBJS} bbsmail: ${BBSBASE} bbsmail.c $(SRCROOT)/innbbsd/str_decode.c $(UTIL_OBJS) $(CCACHE) $(CC) $(CFLAGS) $(LDFLAGS) -o bbsmail -DUSE_ICONV \ - bbsmail.c $(SRCROOT)/innbbsd/str_decode.c $(UTIL_OBJS) + bbsmail.c $(SRCROOT)/innbbsd/str_decode.c $(UTIL_OBJS) $(LIBS) install: $(PROGS) install -d $(BBSHOME)/bin/ diff --git a/util/angel.c b/util/angel.c index 4f7b0a0c..5acd400b 100644 --- a/util/angel.c +++ b/util/angel.c @@ -16,9 +16,6 @@ int nReport = 50; int count; char* mailto = "SYSOP"; -int ListCmp(const void * a, const void * b){ - return *(int*)b - *(int*)a; -} int RejCmp(const void * a, const void * b){ return strcasecmp(SHM->userid[*(int*)a - 1], SHM->userid[*(int*)b - 1]); @@ -100,7 +97,7 @@ void readData(){ rej_list[k++] = i; } - qsort(list, count, sizeof(int[2]), ListCmp); + qsort(list, count, sizeof(int[2]), cmp_int_desc); qsort(rej_list, double_rej, sizeof(int), RejCmp); } diff --git a/util/bbsmail.c b/util/bbsmail.c index 4cc441f2..96f5b512 100644 --- a/util/bbsmail.c +++ b/util/bbsmail.c @@ -9,40 +9,6 @@ extern char *notitle[], *nofrom[], *nocont[]; #endif -int -strip_ansi(char *buf, const 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; -} - int mailalertuid(int tuid) { userinfo_t *uentp=NULL; diff --git a/util/birth.c b/util/birth.c index a3503390..436c37a6 100644 --- a/util/birth.c +++ b/util/birth.c @@ -24,16 +24,6 @@ int bad_user_id(const char *userid) { return 0; } -int Link(const char *src, const char *dst) { - char cmd[200]; - - if (link(src, dst) == 0) - return 0; - - sprintf(cmd, "/bin/cp -R %s %s", src, dst); - return system(cmd); -} - int main(argc, argv) int argc; char **argv; diff --git a/util/deluserfile.c b/util/deluserfile.c index aa5aaa74..f9f16f1f 100644 --- a/util/deluserfile.c +++ b/util/deluserfile.c @@ -7,25 +7,6 @@ #define DELZEROFILE #define USERHOME BBSHOME "/home" -int bad_user_id(const char *userid) -{ - register char ch; - - if (strlen(userid) < 2) - return 1; - - if (!isalpha(*userid)) - return 1; - - if (!strcasecmp(userid, "new")) - return 1; - - while ((ch = *(++userid))) - if (!isalnum(ch)) - return 1; - return 0; -} - void del_file(char *userid) { char buf[200], buf1[200]; @@ -123,7 +104,7 @@ int main(int argc, char **argv) ptr = de->d_name; /* 預防錯誤 */ - if (!bad_user_id(ptr)) + if (is_validuserid(ptr)) { if (!(count++ % 300)) printf(".\n"); diff --git a/util/mailangel.c b/util/mailangel.c index 93d9524b..00906a4c 100644 --- a/util/mailangel.c +++ b/util/mailangel.c @@ -11,14 +11,6 @@ int count; char *mailto = NULL; char *mailfile = NULL; -int ListCmp(const void * a, const void * b){ - return *(int*)b - *(int*)a; -} - -int RejCmp(const void * a, const void * b){ - return strcasecmp(SHM->userid[*(int*)a - 1], SHM->userid[*(int*)b - 1]); -} - void readData(); void sendResult(); void mailUser(char *userid); diff --git a/util/openticket.c b/util/openticket.c index db473fd2..a7a2fd5c 100644 --- a/util/openticket.c +++ b/util/openticket.c @@ -8,17 +8,6 @@ static char *betname[8] = {"Ptt", "Jaky", "Action", "Heat", #define MAX_DES 7 /* 最大保留獎數 */ -int Link(const char *src, const char *dst) -{ - char cmd[200]; - - if (link(src, dst) == 0) - return 0; - - sprintf(cmd, "/bin/cp -R %s %s", src, dst); - return system(cmd); -} - int main(int argc, char **argv) { int money, bet, n, total = 0, ticket[8] = diff --git a/util/outmail.c b/util/outmail.c index 5d5c9d37..eb674890 100644 --- a/util/outmail.c +++ b/util/outmail.c @@ -10,37 +10,6 @@ char *smtpname; int smtpport; char disclaimer[1024]; -/* qp_encode() modified from mutt-1.5.7/rfc2047.c q_encoder() */ -const char MimeSpecials[] = "@.,;:<>[]\\\"()?/= \t"; -char * qp_encode (char *s, size_t slen, const char *d, const char *tocode) -{ - char hex[] = "0123456789ABCDEF"; - char *s0 = s; - - memcpy (s, "=?", 2), s += 2; - memcpy (s, tocode, strlen (tocode)), s += strlen (tocode); - memcpy (s, "?Q?", 3), s += 3; - assert(s-s0+3<slen); - - while (*d != '\0' && s-s0+6<slen) - { - unsigned char c = *d++; - if (c == ' ') - *s++ = '_'; - else if (c >= 0x7f || c < 0x20 || c == '_' || strchr (MimeSpecials, c)) - { - *s++ = '='; - *s++ = hex[(c & 0xf0) >> 4]; - *s++ = hex[c & 0x0f]; - } - else - *s++ = c; - } - memcpy (s, "?=", 2), s += 2; - *s='\0'; - return s0; -} - int waitReply(int sock) { char buf[256]; diff --git a/util/poststat.c b/util/poststat.c index d18a3b70..8dfa6e5a 100644 --- a/util/poststat.c +++ b/util/poststat.c @@ -41,44 +41,6 @@ struct posttop } top[TOPCOUNT], *tp; -/* - woju - Cross-fs rename() - */ - -int Rename(const char *src, const char *dst) -{ - - if (rename(src, dst) == 0) - return 0; -/* - sprintf(cmd, "/bin/mv %s %s", src, dst); - return system(cmd); -*/ - return 0; -} - -int -ci_strcmp(s1, s2) - register char *s1, *s2; -{ - register int c1, c2, diff; - - do - { - c1 = *s1++; - c2 = *s2++; - if (c1 >= 'A' && c1 <= 'Z') - c1 |= 32; - if (c2 >= 'A' && c2 <= 'Z') - c2 |= 32; - if((diff = c1 - c2)) - return (diff); - } - while (c1); - return 0; -} - /* ---------------------------------- */ /* hash structure : array + link list */ diff --git a/util/reaper.c b/util/reaper.c index 348224e9..d058cc55 100644 --- a/util/reaper.c +++ b/util/reaper.c @@ -4,24 +4,12 @@ time4_t now; -int invalid(char *userid) { - int i; - - if(!isalpha(userid[0])) - return 1; - - for(i = 1; i < IDLEN && userid[i]; i++) - if(!isalpha(userid[i]) && !isdigit(userid[i])) - return 1; - return 0; -} - int check(int n, userec_t *u) { time4_t d; char buf[256]; if(u->userid[0] != '\0') { - if(invalid(u->userid)) { + if(!is_validuserid(u->userid)) { syslog(LOG_ERR, "bad userid(%d): %s", n, u->userid); u->userid[0] = '\0'; } else { diff --git a/util/toplazyBBM.c b/util/toplazyBBM.c index 3b881c5f..38f4d55d 100644 --- a/util/toplazyBBM.c +++ b/util/toplazyBBM.c @@ -31,17 +31,6 @@ int bmlostdays_cmp(const void *va, const void *vb) else return 1; } - -int LINK(char* src, char* dst){ - char cmd[200]; - if(symlink(src,dst) == -1) - { - sprintf(cmd, "/bin/cp -R %s %s", src, dst); - return system(cmd); - } - return 0; -} - int main(int argc, char *argv[]) { int bmid, i, j=0; @@ -183,9 +172,9 @@ int main(int argc, char *argv[]) } unlink(genbuf); if(lostdays <= 30){ - LINK(OUTFILE, genbuf); + Link(OUTFILE, genbuf); }else{ - LINK(FIREFILE, genbuf); + Link(FIREFILE, genbuf); } sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname); diff --git a/util/toplazyBM.c b/util/toplazyBM.c index 4789557d..b9a66c26 100644 --- a/util/toplazyBM.c +++ b/util/toplazyBM.c @@ -30,17 +30,6 @@ int bmlostdays_cmp(const void *va, const void *vb) else return 1; } -int LINK(char* src, char* dst) -{ - char cmd[200]; - if(symlink(src,dst) == -1) - { - sprintf(cmd, "/bin/cp -R %s %s", src, dst); - return system(cmd); - } - return 0; -} - int main(int argc, char *argv[]) { int bmid, i, j=0; @@ -194,9 +183,9 @@ int main(int argc, char *argv[]) unlink(genbuf); if (lostdays <= 90) - LINK(OUTFILE, genbuf); + Link(OUTFILE, genbuf); else - LINK(FIREFILE, genbuf); + Link(FIREFILE, genbuf); sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname); diff --git a/util/topusr.c b/util/topusr.c index d2679d39..58f3d86b 100644 --- a/util/topusr.c +++ b/util/topusr.c @@ -91,22 +91,6 @@ int } #endif /* HAVE_TIN */ -int -bad_user_id(const char *userid) -{ - register char ch; - if (strlen(userid) < 2) - return 1; - if (not_alpha(*userid)) - return 1; - while((ch = *(++userid))) - { - if (not_alnum(ch)) - return 1; - } - return 0; -} - int main(int argc, char **argv) { int i, j; @@ -137,7 +121,7 @@ int main(int argc, char **argv) aman.userid[IDLEN]=0; aman.nickname[22]=0; if((aman.userlevel & PERM_NOTOP) || !aman.userid[0] || - bad_user_id(aman.userid) || + !is_validuserid(aman.userid) || strchr(aman.userid, '.')) { continue; diff --git a/util/uhash_loader.c b/util/uhash_loader.c index fe90a545..8696b3c4 100644 --- a/util/uhash_loader.c +++ b/util/uhash_loader.c @@ -3,7 +3,6 @@ #include "bbs.h" #include "fnv_hash.h" -unsigned string_hash(unsigned char *s); void userec_add_to_uhash(int n, userec_t *id, int onfly); void fill_uhash(int onfly); void load_uhash(void); @@ -72,7 +71,7 @@ void checkhash(int h) while(*p != -1) { if(*p <-1 || *p >= MAX_USERS) {*p=-1; return;} - ch = string_hash( SHM->userid[*p])%(1<<HASH_BITS); + ch = StringHash( SHM->userid[*p])%(1<<HASH_BITS); if(ch!=h) { printf("remove %d %d!=%d %d [%s] next:%d\n", @@ -131,30 +130,6 @@ void fill_uhash(int onfly) printf("total %d names %s.\n", usernumber, onfly ? "checked":"loaded"); } -unsigned string_hash(unsigned char *s) -{ - return fnv1a_32_strcase(s, FNV1_32_INIT); -} - -// TODO share code with mbbsd/stuff.c -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 (not_alpha(id[0])) - return 0; - for (i = 1; i < len; i++) - if (not_alnum(id[i])) - return 0; - return 1; -} - void userec_add_to_uhash(int n, userec_t *user, int onfly) { int *p, h, l=0; @@ -170,7 +145,7 @@ void userec_add_to_uhash(int n, userec_t *user, int onfly) return; } - h = string_hash(user->userid)%(1<<HASH_BITS); + h = StringHash(user->userid)%(1<<HASH_BITS); p = &(SHM->hash_head[h]); if(!onfly || SHM->userid[n][0] != user->userid[0] || diff --git a/util/writemoney.c b/util/writemoney.c index 0db8d99d..4b70a22b 100644 --- a/util/writemoney.c +++ b/util/writemoney.c @@ -6,18 +6,6 @@ time4_t now; extern SHM_t *SHM; -int invalid(char *userid) { - int i; - - if(!isalpha(userid[0])) - return 1; - - for(i = 1; i < IDLEN && userid[i]; i++) - if(!isalpha(userid[i]) && !isdigit(userid[i])) - return 1; - return 0; -} - int main() { int num, pwdfd, money; |