Пример #1
0
void add_bbsboard(const board_t *pbt)
{
    struct boardheader newboard;
    char vbuf[PATHLEN], buf[PATHLEN];
    int bid;

    if (!pbt)
        return;
    memset(&newboard, 0, sizeof(newboard));
    strcpy(newboard.filename, pbt->name);
    strcpy(newboard.title, "0[待定]      版面中文名称待定");
    if (getbid(newboard.filename, NULL) > 0) {
        clean_ipc();
        error("%s: getbid error", newboard.filename);
    }
    strcpy(vbuf, "vote/");
    strcat(vbuf, newboard.filename);
    setbpath(buf, newboard.filename);
    /*
     * keep old files.
     * f_rm(buf);
     * f_rm(vbuf);
     */
    if (wrapped_mkdir(buf, 0755) == -1 || wrapped_mkdir(vbuf, 0755) == -1) {
        clean_ipc();
        error("%s: mkdir error", newboard.filename);
    }
    snprintf(newboard.ann_path, 127, "%s/%s", groups[0], newboard.filename);
    newboard.ann_path[127] = '\0';

    /* 默认权限 */
    newboard.level = PERM_SYSOP;

    if (pbt->type == X)
        newboard.level |= PERM_POSTMASK;
    else if (pbt->type == o)
        newboard.level = 0;

    if (add_board(&newboard) == -1) {
        clean_ipc();
        error("%s: add_board error", newboard.filename);
    }
    if ((bid = getbid(newboard.filename, NULL)) == 0) {
        clean_ipc();
        error("%s: getbid error", newboard.filename);
    }

    sprintf(buf, "add board %s", newboard.filename);
    bbslog("user", "%s", buf);
    usage(buf);
}
Пример #2
0
const struct boardheader *getbcache(const char *bname) {
    int i;

    i = getbid(bname,NULL);
    if (i == 0)
        return NULL;
    return &bcache[i - 1];
}
Пример #3
0
int updatelastpost(const char *board)
{
    int pos;

    pos = getbid(board,NULL);       /* board name --> board No. */
    if (pos > 0) {
        getlastpost(board, &brdshm->bstatus[pos - 1].lastpost, &brdshm->bstatus[pos - 1].total);
        return 0;
    } else
        return -1;
}
Пример #4
0
int get_nextid(const char* boardname)
{
    int ret;

    ret=getbid(boardname,NULL);
    if (ret!=0) {
        ret=get_nextid_bid(ret);
    } else
        bbslog("3system", "wrong get_nextid %s", boardname);
    return ret;
}
Пример #5
0
/*
 * 记录分区十大到文件
 */
void writesechot(int secid)
{
    FILE *fp;
    char curfile[256], buf[256];
    char *p;
    int i;
#ifdef READ_SEC_TOP
    struct top_header curr_sectop[10];
    memset(curr_sectop,0,(10*sizeof(struct top_header)));
#endif /* READ_SEC_TOP */

    sprintf(curfile, "etc/posts/day_sec_%s", seccode[secid]);
    if ((fp = fopen(curfile, "w")) != NULL) {
         fprintf(fp, "                \033[34m-----\033[37m=====\033[41m 本日%s区十大热门话题 \033[m=====\033[34m-----\033[m\n\n", seccode[secid]);
        for (i = 0; i < sectopnum[secid]; i++) {
            strcpy(buf, ctime(&sectop[secid][i].date));
            buf[20] = NULL;
            p = buf + 4;

            fprintf(fp,"\033[37m第\033[31m%3d\033[37m 名 \033[37m信区 : \033[33m%-16s\033[37m【\033[32m%s\033[37m】"
                        "\033[36m%4d \033[37m人\033[35m%16s\n     \033[37m标题 : \033[44m\033[37m%-60.60s\033[m\n",
                        (i+1),sectop[secid][i].board,p,sectop[secid][i].number,
                        sectop[secid][i].userid,sectop[secid][i].title);
#ifdef READ_SEC_TOP
            if (i<10) {
                curr_sectop[i].bid=getbid(sectop[secid][i].board,NULL);
                curr_sectop[i].gid=sectop[secid][i].groupid;
            }
#endif /* READ_SEC_TOP */
        }
#ifdef READ_SEC_TOP
        /* 分区十大信息写入共享内存 */
        if (1) {
            const struct boardheader *bh;
            char path[PATHLEN];
            int k;
            for (k=0;k<10;k++) {
                if (!(bh=getboard(publicshm->sectop[secid][k].bid)))
                    continue;
                snprintf(path,PATHLEN,"boards/%s/.TOP.%u",bh->filename,publicshm->sectop[secid][k].gid);
                unlink(path);
            }
            setpublicshmreadonly(0);
            memcpy(publicshm->sectop[secid],curr_sectop,(10*sizeof(struct top_header)));
            setpublicshmreadonly(1);
        }
#endif /* READ_SEC_TOP */

        fclose(fp);
    }
}
Пример #6
0
int setboardmark(const char *board, int i)
{
    int pos;

    pos = getbid(board,NULL);       /* board name --> board No. */
    if (pos > 0) {
        int j;
        j=brdshm->bstatus[pos - 1].updatemark;
        if (i>=0&&i<=1)
            brdshm->bstatus[pos - 1].updatemark = i;
        return j;
    } else
        return -1;
}
Пример #7
0
static int ann_can_access(char *title,const char *board,struct userec *user){
    const struct boardheader *bp;
    char BM[BM_LEN];
    if(strstr(title,"(BM: BMS)")){
        if(board[0]&&getbid(board,&bp)){
            memcpy(BM,bp->BM,(BM_LEN*sizeof(char)));
            return (!chk_currBM(BM,user)?0:2);
        }
        return 0;
    }
    else if(strstr(title,"(BM: SYSOPS)"))
        return (!HAS_PERM(user,PERM_SYSOP)?0:3);
    else
        return 1;
}
Пример #8
0
int fillbcache(struct boardheader *fptr,int idx,void* arg)
{
	int bnum;
    struct BoardStatus * bs;
	char sql[500];

    if (check_see_perm(NULL, fptr)==0 || strlen(fptr->filename) == 0)
        return 0;

    bnum = getbid(fptr->filename,NULL);
    bs = getbstatus(bnum);

	sprintf(sql, "INSERT INTO bonline VALUES ( NULL, '%s', '%d', '%d', \"%d-%d-%d\", '%d', '%d' );",
				fptr->filename, bs->currentusers, bs->nowid, 
				t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min/6);
    if( mysql_real_query( &s, sql, strlen(sql) ))
        printf("%s\n",mysql_error(&s));
    return 0;
}
Пример #9
0
void create_favboard(char *userid)
{
    FILE *fp;
    char goodbrdfile[256];
    char buf[256];
    char *tmp;
	int i=0;

	bzero(favbrd_list, sizeof(struct favbrd_struct)*FAVBOARDNUM);

    favbrd_list_t = 1;
    favbrd_list[0].father = -1;

    sethomefile(goodbrdfile, userid, ".goodbrd");
    if ((fp = fopen(goodbrdfile, "r")) == NULL) {
        return;
    }

    while (!feof(fp)) {
        int k = 0;

        if (i == MAXBOARDPERDIR)
            break;
	bzero(buf,256);
        fgets(buf, 30, fp);
        if (tmp = strstr(buf, "\n"))
            *tmp = 0;
	if(*buf==0) break;
	puts(buf);
        k = getbid(buf, NULL);
        if (k) {
            favbrd_list[0].bid[i] = k - 1;
            i++;
        }
    }
    fclose(fp);
    //unlink(goodbrdfile);
	favbrd_list[0].bnum = i;
    if (favbrd_list_t)
        my_save_favboard(userid);
}
Пример #10
0
static int undo_board(struct boardheader* bh, void* arg) {
	char fname[256];
	setbdir(DIR_MODE_NORMAL, fname, bh->filename);
	undo_index(fname);
	setbdir(DIR_MODE_DIGEST, fname, bh->filename);
	undo_index(fname);
	setbdir(DIR_MODE_THREAD, fname, bh->filename);
	undo_index(fname);
	setbdir(DIR_MODE_MARK, fname, bh->filename);
	undo_index(fname);
	setbdir(DIR_MODE_DELETED, fname, bh->filename);
	undo_index(fname);
	setbdir(DIR_MODE_JUNK, fname, bh->filename);
	undo_index(fname);
	setbdir(DIR_MODE_ORIGIN, fname, bh->filename);
	undo_index(fname);
	setbdir(DIR_MODE_ZHIDING, fname, bh->filename);
	undo_index(fname);
	board_update_toptitle(getbid(bh->filename, NULL), false);
	printf("board %s is undone.\n", bh->filename);
	return 0;
}
Пример #11
0
int generate_board_title(struct boardheader *bh,void* arg)
{
    int fd2, total, i;
    char olddirect[PATHLEN];
    char *ptr;
    struct fileheader * ptr1;
    struct BoardStatus* bs;
    struct stat buf;
	unsigned int iid;

    setbdir(DIR_MODE_NORMAL, olddirect, bh->filename);
    
    if ((fd2 = open(olddirect, O_RDWR, 0664)) == -1) {
		perror(olddirect);
        return 0;
    }

        if (safe_mmapfile_handle(fd2, PROT_READ | PROT_WRITE, MAP_SHARED, &ptr, &buf.st_size) == 0) {
            close(fd2);
            return 0;
        }
        total = buf.st_size / (sizeof(struct fileheader));
        ptr1 = (struct fileheader *) ptr;

		iid = ptr1[total-1].id;

		if(iid <=0) iid = 1;

    end_mmapfile((void *) ptr, buf.st_size, -1);
    close(fd2);

    bs=getbstatus(getbid(bh->filename,NULL));
	if(bs)
    	bs->nowid= iid + 1;

    return 0;
}
Пример #12
0
static inline int process_article(const struct fileheader *f,int n,const struct boardheader *b){
    static const struct flock lck_set={.l_type=F_RDLCK,.l_whence=SEEK_SET,.l_start=0,.l_len=0,.l_pid=0};
    static const struct flock lck_clr={.l_type=F_UNLCK,.l_whence=SEEK_SET,.l_start=0,.l_len=0,.l_pid=0};
    static struct stat st;
    static struct tm *p;
    static char name[BOUND];
    static int fd,i,j,k,l;
    static time_t timestamp;
    static const char *S,*M,*N;
    static void *vp;
    do{
        if((timestamp=get_posttime(f))<from||timestamp>to)
            break;
        if(ISSET(PARAM_P)&&strcmp(f->owner,post))
            break;
        setbfile(name,b->filename,f->filename);
        if(stat(name,&st)==-1||!S_ISREG(st.st_mode)||st.st_size<size)
            break;
        if((fd=open(name,O_RDONLY
#ifdef O_NOATIME
            |O_NOATIME
#endif /* O_NOATIME */
            ,0644))==-1)
            break;
        if(fcntl(fd,F_SETLKW,&lck_set)==-1){
            close(fd);
            break;
        }
        vp=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,fd,0);
        fcntl(fd,F_SETLKW,&lck_clr);
        close(fd);
        if((S=(const char*)vp)==MAP_FAILED)
            break;
        for(p=NULL,j=0,i=0;S[i]&&i<st.st_size;i++){
#define EQUAL(cp,cs)    (((cp)==(cs))||(ISSET(PARAM_I)&&((cp)==toupper(cs))))
            while(j>0&&!EQUAL(P[j],S[i]))
                j=L[j-1];
            if(EQUAL(P[j],S[i]))
                j++;
            if(!P[j]){
                M=&S[l=((i-j)+1)];
                if(!ISSET(PARAM_N)){
                    for(k=0,N=M;!(N<S);N--)
                        if((*N)&0x80)
                            k++;
                    if(!(k&0x01))
                        continue;
                }
                if(!p&&!(p=localtime(&timestamp)))
                    continue;
                count++;
                fprintf(out,"%6d %-20.20s %4d %4s %04d%02d%02d%02d%02d%02d %-17.17s %6d %-13.13s %s\n",
                    n,b->filename,current,mode,(p->tm_year+1900),(p->tm_mon+1),(p->tm_mday),
                    (p->tm_hour),(p->tm_min),(p->tm_sec),f->filename,l,f->owner,f->title);
                if(ISSET(PARAM_S))
                    break;
                j=L[j-1];
            }
#undef EQUAL
        }
        munmap(vp,st.st_size);
        number++;
    }
    while(0);
    return 0;
}

static inline int process_board(const struct boardheader *b,int n,void *v){
    static char name[BOUND];
    do{
        if(ISSET(PARAM_A))
            break;
        if(ISSET(PARAM_U)){
            if(!check_read_perm(user,b))
                return -1;
            break;
        }
        if(ISSET(PARAM_B))
            break;
        if(!public_board(b))
            return -2;
    }
    while(0);
    current=n;
    if(!ISSET(PARAM_Q))
        fprintf(stdout,"正在处理版面 %-29.29s ... ",b->filename);
    if(!ISSET(PARAM_E)){
        mode="版面";
        setbdir(DIR_MODE_NORMAL,name,b->filename);
        APPLY_RECORD(name,process_article,sizeof(struct fileheader),b,0,true);
    }
    if(ISSET(PARAM_D)){
        mode="回收";
        setbdir(DIR_MODE_DELETED,name,b->filename);
        APPLY_RECORD(name,process_article,sizeof(struct fileheader),b,0,true);
    }
    if(ISSET(PARAM_J)){
        mode="自删";
        setbdir(DIR_MODE_JUNK,name,b->filename);
        APPLY_RECORD(name,process_article,sizeof(struct fileheader),b,0,true);
    }
    if(!ISSET(PARAM_Q))
        fprintf(stdout,"%s\n","处理完成!");
    return 0;
}

int main(int argc,char **argv){
#define EXIT(msg)  do{fprintf(stderr,"%s\n",(msg));if(out)fclose(out);exit(__LINE__);}while(0)
    const struct boardheader *board;
    char name[BOUND],path[BOUND];
    const char *desc;
    int ret;
    double cost;
    if(!getcwd(path,BOUND))
        EXIT("获取当前工作目录时发生错误");
    if(chdir(BBSHOME)==-1)
        EXIT("切换工作目录时发生错误...");
    if((mark=time(NULL))==(time_t)(-1))
        EXIT("获取时间时发生错误...");
    resolve_ucache();
    resolve_boards();
    to=mark;
    opterr=0;
    while((ret=getopt(argc,argv,"r:f:t:ab:u:p:djesnio:qh"))!=-1){
        switch(ret){
#define CHECK_CONFLICT(param)   do{if(ISSET(param))EXIT("给定的选项间存在冲突...");}while(0)
#define CHECK_DEPENDENCE(param) do{if(!ISSET(param))EXIT("给定的选项间缺少依赖...");}while(0)
#define CHECK_DUP(param)        do{if(ISSET(param))EXIT("给定的选项中存在重复...");}while(0)
#define SET(param)              do{CHECK_DUP(param);flag|=(param);}while(0)
            case 'r':
                CHECK_CONFLICT(PARAM_F|PARAM_T);
                SET(PARAM_R);
                do{
                    struct tm t,*p;
                    int n;
                    if(!isdigit(optarg[0]))
                        EXIT("选项 -r 的参数无法解析...");
                    n=atoi(optarg);
                    if(!(p=localtime(&mark)))
                        EXIT("解析时间时发生错误...");
                    memcpy(&t,p,sizeof(struct tm));
                    t.tm_hour=0;
                    t.tm_min=0;
                    t.tm_sec=0;
                    if((from=mktime(&t))==(time_t)(-1))
                        EXIT("设定时间时发生错误...");
                }
                while(0);
                break;
#define PARSE2(p)   ((((p)[0]*10)+((p)[1]*1))-('0'*11))
#define PARSE4(p)   ((PARSE2(p)*100)+(PARSE2(&(p)[2])*1))
            case 'f':
                CHECK_CONFLICT(PARAM_R);
                SET(PARAM_F);
                do{
                    struct tm t;
                    int i;
                    for(i=0;optarg[i];i++)
                        if(!isdigit(optarg[i]))
                            break;
                    if(i!=14)
                        EXIT("选项 -f 的参数无法解析...");
                    memset(&t,0,sizeof(struct tm));
                    t.tm_year=(PARSE4(optarg)-1900);
                    t.tm_mon=(PARSE2(&optarg[4])-1);
                    t.tm_mday=PARSE2(&optarg[6]);
                    t.tm_hour=PARSE2(&optarg[8]);
                    t.tm_min=PARSE2(&optarg[10]);
                    t.tm_sec=PARSE2(&optarg[12]);
                    if((from=mktime(&t))==(time_t)(-1))
                        EXIT("设定时间时发生错误...");
                }
                while(0);
                break;
            case 't':
                CHECK_CONFLICT(PARAM_R);
                SET(PARAM_T);
                do{
                    struct tm t;
                    int i;
                    for(i=0;optarg[i];i++)
                        if(!isdigit(optarg[i]))
                            break;
                    if(i!=14)
                        EXIT("选项 -t 的参数无法解析...");
                    memset(&t,0,sizeof(struct tm));
                    t.tm_year=(PARSE4(optarg)-1900);
                    t.tm_mon=(PARSE2(&optarg[4])-1);
                    t.tm_mday=PARSE2(&optarg[6]);
                    t.tm_hour=PARSE2(&optarg[8]);
                    t.tm_min=PARSE2(&optarg[10]);
                    t.tm_sec=PARSE2(&optarg[12]);
                    if((from=mktime(&t))==(time_t)(-1))
                        EXIT("设定时间时发生错误...");
                }
                while(0);
                break;
#undef PARSE2
#undef PARSE4
            case 'a':
                CHECK_CONFLICT(PARAM_B|PARAM_U);
                SET(PARAM_A);
                break;
            case 'b':
                CHECK_CONFLICT(PARAM_A|PARAM_U);
                SET(PARAM_B);
                if(!(current=getbid(optarg,&board)))
                    EXIT("选项 -b 所指定的版面无法获取...");
                break;
            case 'u':
                CHECK_CONFLICT(PARAM_A|PARAM_B);
                SET(PARAM_U);
                do{
                    struct userec *u;
                    if(!getuser(optarg,&u))
                        EXIT("选项 -u 所指定的用户无法获取...");
                    user=u;
                }
                while(0);
                break;
            case 'p':
                SET(PARAM_P);
                snprintf(post,OWNER_LEN,"%s",optarg);
                break;
            case 'd':
                SET(PARAM_D);
                break;
            case 'j':
                SET(PARAM_J);
                break;
            case 'e':
                CHECK_DEPENDENCE(PARAM_D|PARAM_J);
                SET(PARAM_E);
                break;
            case 's':
                SET(PARAM_S);
                break;
            case 'n':
                SET(PARAM_N);
                break;
            case 'i':
                SET(PARAM_I);
                break;
            case 'o':
                SET(PARAM_O);
                if(optarg[0]!='/')
                    snprintf(name,BOUND,"%s/%s",path,optarg);
                else
                    snprintf(name,BOUND,"%s",optarg);
                break;
            case 'q':
                SET(PARAM_Q);
                break;
            case 'h':
                usage();
                return 0;
            default:
                usage();
                EXIT("不可识别的选项...");
                break;
#undef CHECK_CONFLICT
#undef CHECK_DEPENDENCE
#undef CHECK_DUP
#undef SET
        }
    }
    if(from>to){
        usage();
        EXIT("当前时间设定不合法...");
    }
    if(!ISSET(PARAM_Q)&&setvbuf(stdout,NULL,_IONBF,BUFSIZ))
        EXIT("调整文件缓冲时发生错误...");
    if((argc-optind)!=1){
        usage();
        EXIT("不可识别的参数...");
    }
    set_pattern(argv[optind]);
    set_link(argv[optind]);
    if(!size)
        EXIT("模式串不能为空串...");
    if(!ISSET(PARAM_O))
        snprintf(name,BOUND,"%s/res_%lu.us",path,mark);
    if(!(out=fopen(name,"w")))
        EXIT("打开文件时发生错误...");
    fprintf(out,"%6s %-20.20s %4s %4s %-14.14s %-17.17s %6s %-13.13s %s\n",
        "文章号","版面名称"," BID","位置","发表时间","文件名","偏移量","作者","标题");
    if(!(P[0]&0x80))
        flag|=PARAM_N;
    if(ISSET(PARAM_B))
        process_board(board,current,NULL);
    else
        APPLY_BIDS(process_board,NULL);
    fclose(out);
    cost=difftime(time(NULL),mark);
    if(cost>86400){
        cost/=86400;
        desc="天";
    }
    else if(cost>3600){
        cost/=3600;
        desc="小时";
    }
    else if(cost>60){
        cost/=60;
        desc="分钟";
    }
    else
        desc="秒";
    fprintf(stdout,"\n操作已完成! 共处理 %d 篇文章, 获得 %d 处匹配, 耗时 %.2lf %s!\n",
        number,count,cost,desc);
    return 0;
#undef EXIT
}
Пример #13
0
int generate_board_title(struct boardheader *bh,void* arg)
{
    int fd2, size = sizeof(fileheader), total, i;
    struct boardheader btmp;
    char olddirect[PATHLEN];
    char *ptr, *t, *t2;
#ifdef GEN_ORIGIN
    FILE *fp=NULL;
    char opath[512];
#endif
    struct fileheader * ptr1;
    struct search_temp {
        bool has_pre;
        int digest;
        int thread_id;
        int id;
        int next;
    } *index=NULL;
    struct stat buf;
    int gen_threadid;
    struct BoardStatus* bs;

#ifdef GEN_ORIGIN
    setbdir(DIR_MODE_ORIGIN, opath, bh->filename);
#endif
    setbdir(DIR_MODE_NORMAL, olddirect, bh->filename);

    gen_threadid=1;
    if ((fd2 = open(olddirect, O_RDWR, 0664)) == -1) {
        perror(olddirect);
        return 0;
    }

    BBS_TRY {
        if (!safe_mmapfile_handle(fd2,PROT_READ|PROT_WRITE,MAP_SHARED,&ptr,&buf.st_size)) {
            close(fd2);
            return 0;
        }
#ifdef GEN_ORIGIN
        fp = fopen(opath, "wb");
#endif
        total = buf.st_size / size;
        index = (struct search_temp *) malloc(sizeof(*index) * total);
        ptr1 = (struct fileheader *) ptr;
        for (i = 0; i < total; i++, ptr1++) {
            int j;

            t2 = ptr1->title;
            if (!strncmp(t2, "Re:", 3)) {
                index[i].has_pre = true;
                t2 += 4;
            } else
                index[i].has_pre = false;
            index[i].thread_id = 0;
            index[i].digest = simple_digest(t2, ARTICLE_TITLE_LEN);
            for (j = i - 1; j >= 0; j--) {
                struct fileheader *tmppost;

                if (index[j].digest != index[i].digest)
                    continue;
                tmppost = ((struct fileheader *)(ptr + j * size));
                t = tmppost->title;
                if (index[j].has_pre)
                    t += 4;
                if (!strcmp(t, t2)) {
                    index[j].next = i;
                    index[i].thread_id = index[j].thread_id;
                    index[i].next = 0;
                    break;
                }
            }
            if (index[i].thread_id == 0) {
                index[i].thread_id = gen_threadid;
                index[i].id = gen_threadid;
                index[i].next = 0;
                gen_threadid++;
            } else {
                index[i].id = gen_threadid;
                gen_threadid++;
            }
        }
        ptr1 = (struct fileheader *) ptr;
        for (i = 0; i < total; i++, ptr1++) {
            ptr1->id = index[i].id;
            ptr1->groupid = index[i].thread_id;
            ptr1->reid = index[i].thread_id;
#ifdef GEN_ORIGIN
            if (index[i].has_pre == false)
                fwrite(ptr1, 1, sizeof(struct fileheader), fp);
#endif
        }
    }
    BBS_CATCH {
    }
    BBS_END;
    free(index);
    end_mmapfile((void *) ptr, buf.st_size, -1);
    close(fd2);
#ifdef GEN_ORIGIN
    fclose(fp);
#endif
    memcpy(&btmp,getbcache(bh->filename),sizeof(btmp));
    bs=getbstatus(getbid(bh->filename,NULL));
    bs->nowid=gen_threadid + 1;
    set_board(getbid(bh->filename,NULL), &btmp,NULL);
    setboardmark(bh->filename, 1);
    setboardtitle(bh->filename, 1);
    setboardorigin(bh->filename, 1);
    return 0;
}
Пример #14
0
/*
 * mytype 0 本日
 *        1 本周
 *        2 本月
 *        3 本年
 *        4 祝福榜
 */
void writestat(int mytype)
{
	int i;
	char buf[256];
	char *p;
	char curfile[256];
	FILE *fp;

    struct top_header curr_top[10];

    sprintf(curfile, "etc/posts/%s", myfile[mytype]);
    if ((fp = fopen(curfile, "w")) != NULL) {
#ifdef BLESS_BOARD
        if (mytype == 4)
            fprintf(fp, "              \x1b[1;33m── \x1b[31m☆\x1b[33m☆\x1b[32m☆ \x1b[41;32m  \x1b[33m本日十大衷心祝福  \x1b[m\x1b[1;32m ☆\x1b[31m☆\x1b[33m☆ ──\x1b[m\n"
                        "                                                                         %s\x1b[m\n", surfix_bless[1]);
        else
#endif
            fprintf(fp, "                \033[34m-----\033[37m=====\033[41m 本%s \033[m=====\033[34m-----\033[m\n\n", mytitle[mytype]);

        memset(curr_top,0,(10*sizeof(struct top_header)));

        for (i = 0; i < topnum; i++) {

            strcpy(buf, ctime(&top[i].date));
            buf[20] = NULL;
            p = buf + 4;


#ifdef BLESS_BOARD
            if (mytype == 4)
                fprintf(fp,
                        "                                            %s \x1b[1;31m%4d\x1b[0;37m人      %s\x1b[m\n"
                        "\x1b[1m第\x1b[31m%2d \x1b[37m名 \x1b[4%dm %-51.51s\x1b[m \x1b[1;33m%-12s%s\x1b[m\n",
                        p, top[i].number, surfix_bless[(i+1) * 2], i+1, (i) / 2 + 1, top[i].title, top[i].userid, surfix_bless[(i+1) * 2 + 1]);
            else
#endif
            {
                fprintf(fp,"\033[37m第\033[31m%3d\033[37m 名 \033[37m信区 : \033[33m%-16s\033[37m【\033[32m%s\033[37m】"
                    "\033[36m%4d \033[37m人\033[35m%16s\n     \033[37m标题 : \033[44m\033[37m%-60.60s\033[m\n",
                    (i+1),top[i].board,p,top[i].number,top[i].userid,top[i].title);

                /* etnlegend, 2006.05.28, 阅读十大 ... */
                if(!mytype&&i<10){
                    curr_top[i].bid=getbid(top[i].board,NULL);
                    curr_top[i].gid=top[i].groupid;
                }

            }
        }

        if(!mytype){
            const struct boardheader *bh;
            char path[PATHLEN];
            int k;
            for(k=0;k<10;k++){
                if(!(bh=getboard(publicshm->top[k].bid)))
                    continue;
                snprintf(path,PATHLEN,"boards/%s/.TOP.%u",bh->filename,publicshm->top[k].gid);
                unlink(path);
            }
            setpublicshmreadonly(0);
            memcpy(publicshm->top,curr_top,(10*sizeof(struct top_header)));
            publicshm->top_version++;
            setpublicshmreadonly(1);
        }

#ifdef BLESS_BOARD
        if (mytype == 4)
            fprintf(fp, "                                                                         %s\x1b[m", surfix_bless[22]);
#endif
        fclose(fp);
    }
}