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); }
const struct boardheader *getbcache(const char *bname) { int i; i = getbid(bname,NULL); if (i == 0) return NULL; return &bcache[i - 1]; }
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; }
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; }
/* * 记录分区十大到文件 */ 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(§op[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); } }
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; }
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; }
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; }
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); }
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; }
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; }
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(×tamp))) 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 }
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; }
/* * 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); } }