Beispiel #1
0
int main(int argc, char *argv[])
{
    chdir(BBSHOME);
    setuid(BBSUID);
    setgid(BBSGID);
    setreuid(BBSUID, BBSUID);
    setregid(BBSGID, BBSGID);

#ifndef CYGWIN
#undef time
    bbssettime(time(0));
    sleep(1);
#define time(x) bbstime(x)
#endif

    setpublicshmreadonly(0);

#ifndef CYGWIN
    setpublicshmreadonly(1);
#endif
    init_bbslog();
    if (argc > 1) {
        if (strcasecmp(argv[1], "killuser") == 0) {
			//Added by Marvel
            resolve_utmp(); 

            if (resolve_ucache() != 0)
                return -1;
            return dokilluser();
        }
        if (strcasecmp(argv[1], "giveup") == 0) {
            if (resolve_ucache() != 0)
                return -1;
            return doupdategiveupuser();
        }
        if (strcasecmp(argv[1], "allboards") == 0)
            return dokillalldir();
        if (strcasecmp(argv[1], "daemon") == 0)
            return miscd_dodaemon(argv[1], argv[2]);
        if (strcasecmp(argv[1], "killdir") == 0)
            return dokilldir(argv[2]);
        if (strcasecmp(argv[1], "flush") == 0) {
            if (resolve_ucache() != 0)
	              return -1;
            resolve_boards();
            flushdata();
            return 0;
        }
        return miscd_dodaemon(NULL, argv[1]);
    }
    printf("Usage : %s daemon: to run as a daemon (this is the most common use)\n", argv[0]);
    printf("        %s killuser: to kill old users\n", argv[0]);
    printf("        %s giveup: to unlock given-up users\n", argv[0]);
    printf("        %s killdir <BOARDNAME>: to delete old file in <BOARDNAME>\n", argv[0]);
    printf("        %s allboards: to delete old files in all boards\n", argv[0]);
    printf("        %s flush: to synchronize .PASSWDS and .BOARDS to disk\n", argv[0]);
    printf("That's all, folks. See doc/README.SYSOP for more details\n");

    return 0;
}
Beispiel #2
0
main()
{
	time_t t;
	struct tm tt;

    chdir(BBSHOME);

	if (load_birthfile()<=0){
		printf("error read birthfile\n");
		exit(0);
	}

	t=time(0);
	if (localtime_r(&t, &tt)==NULL) exit(0);

	birthmonth = tt.tm_mon + 1;
	birthday = tt.tm_mday;

    resolve_ucache();
    resolve_boards();
    resolve_utmp();

	srand(time(0));
    apply_users(mailuser,NULL);
}
Beispiel #3
0
// Puts struct userec in *'u' according to ('uid' - 1).
int getuserbyuid(struct userec *u, int uid)
{
	if (resolve_ucache() == -1)
		return -1;
	*u = uidshm->passwd[uid - 1];
	return uid;
}
Beispiel #4
0
int main(int argc, char **argv)
{
    int i,j,k;
    char * s;
    chdir(BBSHOME);
    resolve_boards();
    resolve_ucache();
    resolve_utmp();
    memset(count, 0, 200*sizeof(int));
    apply_ulist_addr((APPLY_UTMP_FUNC)check,NULL);
    for (i=0;i<200;i++)order[i]=i;
    for (i=0;i<200;i++)
        for (j=i+1;j<200;j++)
            if (count[order[i]]<count[order[j]]) {
                k=order[i];
                order[i]=order[j];
                order[j]=k;
            }
    j=0;
    for (i=0;i<200;i++) {
        s = ModeType(order[i]);
        if (s[0]&&strcmp(s,unknown)) {
            j++;
            printf("%2d  %10s  %4d  %.2lf%%\n", j, s, count[order[i]], (double)count[order[i]]/total*100);
        }
    }
    return 0;
}
Beispiel #5
0
// Get 'userid' according to ('uid' - 1).
int getuserid(char *userid, int uid, size_t len)
{
	if (resolve_ucache() == -1)
		return -1;
	strlcpy(userid, uidshm->userid[uid - 1], len);
	return 0;
}
Beispiel #6
0
int main(int argc, char **argv)
{
    struct userec *user;
    unsigned char accessed[2];
    char path[PATHLEN];
    int ret;
    if (argc != 5) {
        printf("usage: %s FILENAME USERID TITLE BOARD\n", argv[0]);
        return 0;
    }
    if (!getcwd(path, PATHLEN))
        return -1;
    chdir(BBSHOME);
    resolve_boards();
    resolve_ucache();
    if (!getuser(argv[2], &user)) {
        printf("user %s not found!\n", argv[2]);
        return -2;
    }
    accessed[0] = 0; accessed[1] = 0;
    if (argv[1][0] != '/') {
        strcat(path, "/");
        strcat(path, argv[1]);
    } else {
        memcpy(path, argv[1], PATHLEN);
    }
    if (access(path, R_OK)) {
        printf("file %s not found!\n", argv[1]);
        return -3;
    }
    ret = post_file_alt(path, user, argv[3], argv[4], NULL, 0x04, accessed);
    printf("done, return value = %d\n", ret);
    return 0;
}
Beispiel #7
0
char* u_namearray(char buf[][IDLEN + 1], int* pnum, char* tag)
{
    register struct UCACHE *reg_ushm = uidshm;
    register char *ptr, tmp;
    register int n, total;
    char    tagbuf[STRLEN];
    int     ch, num = 0;
    resolve_ucache();
    if (*tag == '\0')
    {
        *pnum = reg_ushm->number;
        return reg_ushm->userid[0];
    }
    for (n = 0; tag[n] != '\0'; n++)
    {
        tagbuf[n] = chartoupper(tag[n]);
    }
    tagbuf[n] = '\0';
    ch = tagbuf[0];
    total = reg_ushm->number;
    for (n = 0; n < total; n++)
    {
        ptr = reg_ushm->userid[n];
        tmp = *ptr;
        if (tmp == ch || tmp == ch - 'A' + 'a')
            if (chkstr(tag, tagbuf, ptr))
                strcpy(buf[num++], ptr);
    }
    *pnum = num;
    return buf[0];
}
Beispiel #8
0
int
main(int argc, char ** argv)
{
    struct userec *user = NULL;

    chdir(BBSHOME);
    resolve_ucache();
    resolve_boards();
    if (argc == 2 && !strcmp(argv[1], "-a"))
        apply_users(query_BM, NULL);
    else if (argc == 3 && !strcmp(argv[1], "-u"))
    {
        getuser(argv[2], &user);
        if (user == NULL)
        {
            fprintf(stderr, "User %s not found.\n", argv[1]);
            return -1;
        }
        user->usedspace = 0xFFFF;
    }
    else if (argc == 3 && !strcmp(argv[1], "-s"))
    {
        getuser(argv[2], &user);
        if (user == NULL)
        {
            fprintf(stderr, "User %s not found.\n", argv[1]);
            return -1;
        }
        printf("User %s usedspace: %u bytes.\n", user->userid, user->usedspace);
    }	else
        usage();

    return 0;
}
Beispiel #9
0
int main(int argc, char *argv[]) {
	chdir(BBSHOME); //进入BBS用户主目录
	setuid(BBSUID); //将进程的 用户ID
	setgid(BBSGID); //组ID设置成BBS
	setreuid(BBSUID, BBSUID); //设置有效用户ID	
	setregid(BBSGID, BBSGID); //有效组ID为BBS

	if (argc <= 1) {
		printf("usage: daemon | flushed | reload\n");
		exit(0);
	}
	if ( !strcasecmp(argv[1], "daemon") ) { // miscd daemon
		switch (fork()) { //后台程序:需要创建一个子进程,由子进程杀死父进程
			case -1: //
				printf("cannot fork\n");
				exit(0);
				break;
			case 0: // 子进程
				break;
			default:
				exit(0); //父进程
				break;
		}

		if (load_ucache() != 0) { //将用户的数据映射到内存
			printf("load ucache error\n");
			exit(-1);
		}

		if (resolve_boards() < 0)
			exit(-1);
		atexit(do_exit); //注册退出前运行的函数.正常退出前须执行此函数

		while (1) { //循环
			refresh_utmp(); //刷新用户临时数据
			b_closepolls(); //关闭投票
			flush_ucache(); //将用户在内存中的数据写回.PASSWDS
			flush_bcache();
			sleep(60 * 15); //睡眠十分钟,即每十五分钟同步一次.        
		}
	} else if ( !strcasecmp(argv[1], "flushed") ) { //miscd flushed
		if (resolve_ucache() == -1)
			exit(1);
		flush_ucache();
		flush_bcache();
	} else if ( !strcasecmp(argv[1], "reload") ) { //miscd reload
		if (load_ucache() != 0) {
			printf("load ucache error\n");
			exit(-1);
		}
	} else {
		printf("usage: daemon | flushed | reload\n");
		exit(0);
	}

	return 0;
}
Beispiel #10
0
int main(int argc, char **argv)
{
    chdir(BBSHOME);
    resolve_boards();
    resolve_ucache();

    apply_boards(calcboard, NULL);
    return 0;
}
Beispiel #11
0
int searchuser(char* userid)
{
    register int i;
    resolve_ucache();
    //	for (i = 0; i < uidshm->number; i++)
    for (i = 0; i < MAXUSERS; i++)
        if (!ci_strncmp(userid, uidshm->userid[i], IDLEN + 1))
            return i + 1;
    return 0;
}
Beispiel #12
0
main()
{
   struct userec ur;
   chdir(BBSHOME);
   setuid(BBSUID);
   setgid(BBSGID);
   resolve_ucache();
   strcpy(ur.userid,"KCN");
//   refriend(&ur,NULL);
   apply_users(refriend,NULL);
}
Beispiel #13
0
int searchnewuser()
{
    register int num, i;
    resolve_ucache();
    num = uidshm->number;
    for (i = 0; i < num; i++)
        if (uidshm->userid[i][0] == '\0')
            return i + 1;
    if (num < MAXUSERS)
        return (num + 1);
    return 0;
}
Beispiel #14
0
// Returns realtime count of all users who has logged on more than once.
int allusers(void)
{
	if (resolve_ucache() == -1)
		return 0;
	struct userec *user;
	struct userec *end = uidshm->passwd 
			+ sizeof(uidshm->passwd) / sizeof(uidshm->passwd[0]);
	int count = 0;
	for (user = uidshm->passwd; user != end; ++user)
		count += (user->numlogins != 0 && user->userid[0] != '\0');
	return count;
}
Beispiel #15
0
int main(int argc, char **argv)
{
    if(argc<=1) return 0;
    mode = atoi(argv[1]);
    chdir(BBSHOME);
    resolve_boards();
    resolve_ucache();
    resolve_utmp();
    apply_ulist_addr((APPLY_UTMP_FUNC)check,NULL);
    printf("%s: %d\n", ModeType(mode), count);
    return 0;
}
Beispiel #16
0
/**
 * Get an web request handler according to its name.
 * @return handler pointer if found, NULL otherwise.
 */
static const web_handler_t *_get_handler(void)
{
	char *surl = getenv("SCRIPT_NAME");
	if (!surl)
		return NULL;

	char *name = strrchr(surl, '/');
	if (!name)
		name = surl;
	else
		++name;

	char buf[16];
	strlcpy(buf, name, sizeof(buf));
	char *tmp = strrchr(buf, '.');
	if (tmp)
		*tmp = '\0';

	web_handler_t h = { .name = buf, .func = NULL, .status = 0 };
	return bsearch(&h, handlers, ARRAY_SIZE(handlers), sizeof(h),
			compare_handler);
}

/**
 * Initialization before entering FastCGI loop.
 * @return 0 on success, -1 on error.
 */
static int initialize(void)
{
	srand(time(NULL) * 2 + getpid());

	if (chdir(BBSHOME) != 0)
		return -1;

	if (setgid(BBSGID) != 0)
		return -1;
	if (setuid(BBSUID) != 0)
		return -1;

	if (resolve_ucache() == -1)
		return -1;

	if (resolve_boards() < 0)
		return -1;
	if (!brdshm)
		return -1;

	const char *socket_path = getenv("FBBS_SOCKET_PATH");
	if (!socket_path || backend_proxy_connect(socket_path, true) < 0)
		return -1;

	return 0;
}
Beispiel #17
0
// Refreshes utmp(cache for online users.)
int refresh_utmp(void)
{
	int utmpfd, ucachefd;
	struct user_info *uentp;
	int n;
	int count = 0; // Online users count.
	time_t now;

	resolve_utmp();
	if (resolve_ucache() == -1)
		return -1;
	now = time(NULL);
	// Lock caches.
	utmpfd = utmp_lock();
	if (utmpfd == -1)
		return -1;
	ucachefd = ucache_lock();
	if (ucachefd == -1)
		return -1;

	memset(uidshm->status, 0, sizeof(uidshm->status));
	for (n = 0; n < USHM_SIZE; n++) {
		uentp = &(utmpshm->uinfo[n]);
		if (uentp->active && uentp->pid) {
			 // See if pid exists.
			if (bbskill(uentp, 0) == -1) {
				memset(uentp, 0, sizeof(struct user_info));
				continue;
			} else {
				// Kick idle users out.
				if (uentp->mode != BBSNET
						&& now - uentp->idle_time > IDLE_TIMEOUT) {
					bbskill(uentp, SIGHUP);
					memset(uentp, 0, sizeof(struct user_info));
				} else {
					// Increase status.
					uidshm->status[uentp->uid - 1]++;
					// Count online users.
					++count;
				}
			}
		}
	}
	utmpshm->total_num = count;
	// Get count of all users from ucache.
	utmpshm->usersum = allusers();
	// Unlock caches.
	ucache_unlock(ucachefd);
	utmp_unlock(utmpfd);
	return count;
}
Beispiel #18
0
Datei: lvars.c Projekt: wyat/kbs
int init_all(ARG_VOID)
{
    int ret=0;
    chdir(BBSHOME);
    get_publicshm();
    resolve_boards();
    ret=resolve_ucache();
    resolve_utmp();
#ifndef THREADSAFE
    init_sessiondata(getSession());
#endif
    resolve_guest_table();
    return ret;
}
Beispiel #19
0
static int initialize_ext()
{
    char old_cwd[256];
    getcwd(old_cwd, sizeof(old_cwd));

    chdir(BBSHOME);
    get_publicshm();
    resolve_ucache();
    resolve_utmp();
    resolve_boards();
    init_bbslog();
    www_data_init();
    ext_init = 1;

    chdir(old_cwd);
    return ext_init;
}
Beispiel #20
0
int main(int argc,char **argv)
{
    if (argc<=2) {
        printf("usage: statguy login|post|stay|all|birthday <total>\n");
        return -1;
    }
    if (!strcmp(argv[1], "login")) flag = 0;
    if (!strcmp(argv[1], "post")) flag = 1;
    if (!strcmp(argv[1], "stay")) flag = 2;
    if (!strcmp(argv[1], "all")) flag = 3;
    if (!strcmp(argv[1], "birthday")) {
        time_t now;
        struct tm *tmnow;
        flag = 4;
        now = time(0);
        now += 86400;  /* 直接算明天比较准啦! +1 不准 */
        tmnow = localtime(&now);
        tm_mon = tmnow->tm_mon + 1;
        tm_mday = tmnow->tm_mday;
    }
    total=atoi(argv[2]);
    if (!total) {
        printf("error: <total> must be an integer and greater than zero!\n");
        return -2;
    }
    chdir(BBSHOME);
    resolve_ucache();
    resolve_boards();
    lib = malloc(sizeof(struct libstruct)*total);
    memset(lib, 0, sizeof(struct libstruct)*total);
    apply_users(statit, NULL);
    if (flag == 4) {
        int i;
        printf("\n%s明日寿星名表\n\n", NAME_BBS_CHINESE);
        printf("以下是 %d 月 %d 日的寿星:\n\n",tm_mon, tm_mday);
        for (i=0; i<cur; i++) {
            printf(" ** %-15.15s (%s)\n", lib[i].id, lib[i].nick);
        }
        printf("\n\n总共有 %d 位寿星。\n", cur);
    } else
        show();
    return 0;
}
Beispiel #21
0
// Returns the place of 'userid' in cache for all users, 0 if not found.
int searchuser(const char *userid)
{
	register int i;
	int a1, a2;
	int key;

	if (resolve_ucache() == -1)
		return 0;
	key = uhashkey(userid, &a1, &a2);
	i = uidshm->hash[a1][a2][key];
	while (i) {
		if (!strncasecmp(userid, uidshm->userid[i - 1],
				sizeof(uidshm->userid[0]))) {
			return i;
		}
		i = uidshm->next[i - 1];
	}
	return 0;
}
Beispiel #22
0
int main(int argc, char **argv)
{
    char mdir[256];
    char mdir_bak[256];
    char mdir_new[256];
    struct stat st;
    int fd;
    char touser[20];
    int len;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s fromuser\n", argv[0]);
        return -1;
    }
    chdir(BBSHOME);
    resolve_ucache();
    while (!feof(stdin)) {
        if (fgets(touser, sizeof(touser) - 1, stdin) == NULL)
            return -1;
        touser[sizeof(touser) - 1] = '\0';
        len = strlen(touser);
        if (touser[len - 1] == '\n')
            touser[len - 1] = '\0';
        setmailfile(mdir, touser, ".DIR");
        if (stat(mdir, &st) < 0) {
            fprintf(stderr, "User '%s' not found.\n", touser);
            continue;
        }
        sprintf(mdir_bak, "%s.BAK", mdir);
        f_cp(mdir, mdir_bak, 0);
        sprintf(mdir_new, "%s.NEW", mdir);
        if ((fd = open(mdir_new, O_RDWR | O_CREAT, 0644)) > 0) {
            delete_all_mail(fd, touser, mdir, sizeof(struct fileheader),
                            (RECORD_FUNC_ARG)cmpauthor, argv[1]);
            close(fd);
            f_mv(mdir_new, mdir);
        }
    }
    return 0;
}
Beispiel #23
0
int getnewutmpent(struct user_info *up)
{
	int utmpfd, ucachefd;
	struct user_info *uentp;
	int i;

	resolve_utmp();
	if (resolve_ucache() == -1)
		return -1;

	utmpfd=utmp_lock();
	if (utmpfd == -1) {
		return -1;
	}

	if (utmpshm->max_login_num < get_online())
		utmpshm->max_login_num = get_online();
	for (i = 0; i < USHM_SIZE; i++) {
		uentp = &(utmpshm->uinfo[i]);
		if (!uentp->active || !uentp->pid)
			break;
	}
	if (i >= USHM_SIZE) {
		utmp_unlock(utmpfd);
		return -2;
	}
	utmpshm->uinfo[i] = *up;
	utmpshm->total_num++;

	utmp_unlock(utmpfd);

	ucachefd=ucache_lock();
	uidshm->status[up->uid-1]++;
	ucache_unlock(ucachefd);

	return i + 1;
}
Beispiel #24
0
static char *u_namearray(char buf[][IDLEN + 1], int *pnum, const char *tag)
{
	char *ptr;
	int i, total, num = 0;
	char tagbuf[STRLEN];
	if (resolve_ucache() == -1)
		exit(0);
	if (*tag == '\0') {
		*pnum = uidshm->number;
		return uidshm->userid[0];
	}
	strlcpy(tagbuf, tag, sizeof(tagbuf));
	size_t size = strlen(tagbuf);
	for (i = 0; tagbuf[i] != '\0'; i++)
		tagbuf[i] = toupper(tagbuf[i]);
	total = uidshm->number;
	for (i = 0; i < total; i++) {
		ptr = uidshm->userid[i];
		if (!strncasecmp(ptr, tagbuf, size))
			memcpy(buf[num++], ptr, sizeof(buf[0]));
	}
	*pnum = num;
	return buf[0];
}
Beispiel #25
0
int 
main(int argc, char ** argv)
{
    struct userec *user = NULL;

    chdir(BBSHOME);
    resolve_ucache();
    if (argc == 2 && !strcmp(argv[1], "-a"))
        apply_users(sync_mailsize, NULL);
    else if (argc == 3 && !strcmp(argv[1], "-u"))
    {
        getuser(argv[2], &user);
        if (user == NULL)
        {
            fprintf(stderr, "User %s not found.\n", argv[2]);
            return -1;
        }
        sync_mailsize(user, NULL);
    }
    else
        usage();

    return 0;
}
Beispiel #26
0
int main(int argc, char **argv)
{
    FILE* fin,*fout1,*fout2;
	char genbuf[8][256];
	char* ptr;
	int i;
	struct userec * uc;
	int now;
    int exit = 0,goonsearch = 1;
	char userid[IDLEN+2];

	chdir(BBSHOME);
	
	resolve_ucache();
	resolve_utmp();

    now = time(NULL);
	if((fin = fopen("pre_register","r+")) == NULL)
	{
	    printf("open pre_register file failed.\n");
	    return 0;
	}
	if((fout1 = fopen("pre_register1","w")) == NULL)
	{
	    fclose(fin);
	    printf("open pre_register1 file failed.\n");
	    return 0;
	}
	if((fout2 = fopen("new_register","a")) == NULL)
	{
	    fclose(fin);
		fclose(fout1);
	    printf("open pre_register file failed.\n");
	    return 0;
	}

    writew_lock(fileno(fin), 0, SEEK_SET, 0);
	while(!exit){
	    for(i = 0; i < 8;i++)
		{
            if(fgets(genbuf[i], 256, fin) == NULL){
			    exit = 1;
			    break;
			}
		}
		if(exit == 1)break;
		if(goonsearch){
			strncpy(userid,genbuf[1]+8,IDLEN);
			if((ptr=strchr(userid,'\n')) != NULL)*ptr = 0;
			userid[IDLEN]=0;
			if(getuser(userid,&uc) == 0)
			{
		    	printf("genbuf[1] is %s",genbuf[1]);
		    	printf("%s not found\n",userid);
		    	continue;  //get userid's userec
			}
			if((now - uc->firstlogin) > REGISTER_WAIT_TIME)
			{
            		for(i = 0; i < 8;i++)fputs(genbuf[i],fout2);
			}
			else{
				goonsearch=0;
            			for(i = 0; i < 8;i++)fputs(genbuf[i],fout1);
			}
		}else{
			for(i = 0;i< 8; i++)fputs(genbuf[i],fout1);
		}
    }
//    rewind(fout1);
//    ftruncate(fileno(fin),0);
//    while(fgets(genbuf[0],256,fout1))
//    	fputs(genbuf[0],fin);
    un_lock(fileno(fin), 0, SEEK_SET, 0);
    fclose(fin);
    fclose(fout1);
    fclose(fout2);
	
	f_mv("pre_register1","pre_register");
}
Beispiel #27
0
void getuserid(char* userid, unsigned short int uid)
{
    resolve_ucache();
    strcpy(userid, uidshm->userid[uid - 1]);
}
Beispiel #28
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
}