Пример #1
0
void readData(){
    int i, j;
    userec_t user;
    FILE* fp;

    attach_SHM();

    fp = fopen(BBSHOME "/.PASSWDS", "rb");
    j = count = 0;
    while (fread(&user, sizeof(userec_t), 1, fp) == 1) {
	++j; /* j == uid */
	if (user.userlevel & PERM_ANGEL) {
	    ++count;
	    ++total[j]; /* make all angel have total > 0 */
	} else { /* don't have PERM_ANGEL */
	    total[j] = INT_MIN;
	}
    }
    fclose(fp);

    list = (int *) malloc(count * sizeof(int));
    j = 0;
    for (i = 1; i <= MAX_USERS; ++i)
	if (total[i] > 0) {
	    list[j] = i;
	    ++j;
	}
}
Пример #2
0
int main(int argc, char **argv)
{
    int     i = 0;
	
    chdir(BBSHOME);
    initsetproctitle(argc, argv, environ);
    if( argc >= 2 ){
	if( strcmp(argv[1], "init") == 0 ){
	    /* in this case, do NOT run attach_SHM here.
	       because uhash_loader is not run yet.      */
	    return SHMinit(argc - 1, &argv[1]);
	}

	attach_SHM();
	/* shmctl doesn't need resolve_boards() first */
	//resolve_boards();
	resolve_garbage();
	resolve_fcache();
	for( i = 0 ; cmd[i].func != NULL ; ++i )
	    if( strcmp(cmd[i].cmd, argv[1]) == 0 ){
		return cmd[i].func(argc - 1, &argv[1]);
	    }
    }
    if( argc == 1 || cmd[i].func == NULL ){
	/* usage */
	printf("usage: shmctl [command] [options]\n");
	printf("commands:\n");
	for( i = 0 ; cmd[i].func != NULL ; ++i )
	    printf("\t%-15s%s\n", cmd[i].cmd, cmd[i].descript);
    }
    return 0;
}
Пример #3
0
void
setup_program()
{
    setuid(BBSUID);
    setgid(BBSGID);
    chdir(BBSHOME);

    attach_SHM();
}
Пример #4
0
void
setup_program()
{
    setuid(BBSUID);
    setgid(BBSGID);
    chdir(BBSHOME);

#ifdef BOARDD_MT
    g_threadpool = threadpool_new(NUM_THREADS);
#endif

    attach_SHM();
}
Пример #5
0
int main(int argc, char *argv[])
{
    int     ch, sfd;
    char   *iface_ip = REGMAILD_ADDR;
    int     as_daemon = 1;

    Signal(SIGPIPE, SIG_IGN);

    chdir(BBSHOME);
    attach_SHM();

    /* Give up root privileges: no way back from here */
    setgid(BBSGID);
    setuid(BBSUID);

    while ( (ch = getopt(argc, argv, "i:hD")) != -1 )
	switch( ch ){
	case 'i':
	    iface_ip = optarg;
	    break;
        case 'D':
            as_daemon = 0;
            break;
	case 'h':
	default:
	    fprintf(stderr, "usage: %s [-D] [-i [interface_ip]:port]\n", argv[0]);
	    return 1;
	}

    if ( (sfd = tobind(iface_ip)) < 0 )
	return 1;

    if (as_daemon) daemonize(BBSHOME "/run/regmaild.pid", BBSHOME "/log/regmaild.log");
    regmaildb_open(&g_Db, EMAILDB_PATH);
    reload_unambiguous_user_list();

    event_init();
    event_set(&ev_listen, sfd, EV_READ | EV_PERSIST, listen_cb, &ev_listen);
    event_add(&ev_listen, NULL);
    fprintf(stderr, "start dispatch.\r\n");
    event_dispatch();

    return 0;
}
Пример #6
0
int main()
{
    int num, pwdfd, money;
    userec_t u;

    attach_SHM();

    if ((pwdfd = open(fn_passwd, O_WRONLY)) < 0)
        exit(1);
    for (num=1; num <= SHM->number; num++) {
        lseek(pwdfd, sizeof(userec_t) * (num - 1) +
              ((char *)&u.money - (char *)&u), SEEK_SET);
        money = moneyof(num);
        write(pwdfd, &money, sizeof(int));
    }
    close(pwdfd);

    return 0;
}
Пример #7
0
int SHMinit(int argc, char **argv)
{
    int     ch;
    int     no_uhash_loader = 0;
    while( (ch = getopt(argc, argv, "n")) != -1 )
	switch( ch ){
	case 'n':
	    no_uhash_loader = 1;
	    break;
	default:
	    printf("usage:\tshmctl\tSHMinit\n");
	    return 0;
	}

    puts("loading uhash...");
    system("bin/uhash_loader");

    attach_SHM();

    puts("loading bcache...");
    reload_bcache();

    puts("building BMcache...");
    bBMC(1, argv);

#if 0
    puts("building class...");
    buildclass(0, 0);
#endif

    if( !no_uhash_loader ){
	puts("utmpsortd...");
	utmpsortd(1, argv);
    }

#ifdef NOKILLWATERBALL
    puts("nkwbd...");
    nkwbd(1, argv);
#endif

    return 0;
}
Пример #8
0
int main(int argc, char **argv)
{
    int     ch, allboards = 0, i;
    boardheader_t  *bptr;
    while( (ch = getopt(argc, argv, "ah")) != -1 )
	switch( ch ){
	case 'a':
	    allboards = 1;
	    break;
	case 'h':
	    usage();
	    return 0;
	}

    chdir(BBSHOME);
    attach_SHM();
    argc -= optind;
    argv += optind;
    now = time(NULL);
    if( allboards ){
	for( i = 0 ; i < MAX_BOARD ; ++i ){
	    bptr = &bcache[i];
	    if( bptr->brdname[0] &&
		!(bptr->brdattr & (BRD_TOP | BRD_GROUPBOARD)) &&
		bptr->brdattr & BRD_HIDE )
		chkhbf(bptr);
	}
    }
    else if( argc > 0 ){
	int     bid;
	for( i = 0 ; i < argc ; ++i )
	    if( (bid = getbnum(argv[i])) != 0 ) // XXX: bid start 1
		chkhbf(getbcache(bid));
	    else
		fprintf(stderr, "%s not found\n", argv[i]);
    }
    else
	usage();

    return 0;
}
Пример #9
0
int main(void)
{
    attach_SHM();

    printf("#!/usr/bin/perl\n"
           "# this is auto-generated perl module from boardlist.c\n"
           "# please do NOT modify this directly!\n"
           "# usage: make boardlist; ./boardlist | perl\n"
           "use DB_File;\n"
	   "use Data::Serializer;\n"
	   "\n"
	   "unlink 'boardlist.db', 'boardlist.list';\n"
	   "$serializer = Data::Serializer->new(serializer => 'Storable', digester => 'MD5',compress => 0,);\n"
           "tie %%db, 'DB_File', 'boardlist.db', (O_RDWR | O_CREAT), 0666, $DB_HASH;\n"
	   );
    dumpclass(1);
    dumpdetail();
    dumpallbrdname();
    printf("untie %%db;\n");
    return 0;
}
Пример #10
0
int main(int argc, char **argv)
{
    int     sfd, index, i;
    attach_SHM();
    if( (sfd = toconnect(UTMPD_ADDR)) < 0 ) {
	printf("connect fail\n");
	return 1;
    }

    index = -1;
    towrite(sfd, &index, sizeof(index));
    for( i = 0 ; i < USHM_SIZE ; ++i )
	if( towrite(sfd, &SHM->uinfo[i].uid, sizeof(SHM->uinfo[i].uid)) <= 0 ||
	    towrite(sfd, SHM->uinfo[i].myfriend,
		    sizeof(SHM->uinfo[i].myfriend)) <= 0                     ||
	    towrite(sfd, SHM->uinfo[i].reject,
		    sizeof(SHM->uinfo[i].reject)) <= 0                       ){
	    fprintf(stderr, "sync error %d\n", i);
	}
    return 0;
}
Пример #11
0
int main(int argc, char **argv)
{
    FILE *fp;

    attach_SHM();
    resolve_boards();
    if(argc != 5) {
	printf("usage: %s <board name> <title> <owner> <file>\n", argv[0]);
	return 0;
    }
    
    if(strcmp(argv[4], "-") == 0)
	fp = stdin;
    else {
	fp = fopen(argv[4], "r");
	if(!fp) {
	    perror(argv[4]);
	    return 1;
	}
    }
    keeplog(fp, argv[1], argv[2], argv[3]);
    return 0;
}
Пример #12
0
int main() {
    int i, j, k;
    FILE *fp;
    int max, item, maxhoroscope;

    int act[12];

    char *name[13] =
    {"¨d¦Ï",
     "ª÷¤û",
     "Âù¤l",
     "¥¨ÃÉ",
     "·à¤l",
     "³B¤k",
     "¤Ñ¯¯",
     "¤ÑÃÈ",
     "®g¤â",
     "¼¯½~",
     "¤ô²~",
     "Âù³½",
     ""
    };
    char *blk[10] =
    {
	"  ", "¢j", "¢k", "¢l", "¢m",
	"¢n", "¢o", "¢p", "¢i", "¢i",
    };

    attach_SHM();
    memset(act, 0, sizeof(act));
    if(passwd_init())
	exit(1);
    for(k = 1; k <= MAX_USERS; k++) {
	passwd_query(k, &user);
	if(!user.userid[0])
	    continue;
	switch (user.month)
	{
	case 1:
	    if (user.day <= 19)
		act[9]++;
	    else
		act[10]++;
	    break;
	case 2:
	    if (user.day <= 18)
		act[10]++;
	    else
		act[11]++;
	    break;
	case 3:
	    if (user.day <= 20)
		act[11]++;
	    else
		act[0]++;
	    break;
	case 4:
	    if (user.day <= 19)
		act[0]++;
	    else
		act[1]++;
	    break;
	case 5:
	    if (user.day <= 20)
		act[1]++;
	    else
		act[2]++;
	    break;
	case 6:
	    if (user.day <= 21)
		act[2]++;
	    else
		act[3]++;
	    break;
	case 7:
	    if (user.day <= 22)
		act[3]++;
	    else
		act[4]++;
	    break;
	case 8:
	    if (user.day <= 22)
		act[4]++;
	    else
		act[5]++;
	    break;
	case 9:
	    if (user.day <= 22)
		act[5]++;
	    else
		act[6]++;
	    break;
	case 10:
	    if (user.day <= 23)
		act[6]++;
	    else
		act[7]++;
	    break;
	case 11:
	    if (user.day <= 22)
		act[7]++;
	    else
		act[8]++;
	    break;
	case 12:
	    if (user.day <= 21)
		act[8]++;
	    else
		act[9]++;
	    break;
	}
    }

    for (i = max = maxhoroscope = 0; i < 12; i++)
    {
	if (act[i] > max)
	{
	    max = act[i];
	    maxhoroscope = i;
	}
    }

    item = max / 30 + 1;

    if ((fp = fopen(BBSHOME"/etc/horoscope", "w")) == NULL)
    {
	printf("cann't open etc/horoscope\n");
	return 1;
    }

    for (i = 0; i < 12; i++)
    {
	fprintf(fp, " %s®y ", name[i]);
	for (j = 0; j < act[i] / item; j++)
	{
	    fprintf(fp, "%2s", blk[9]);
	}
    /* ¬°¤F­è¦n¤@­¶ */
	if (i != 11)
	    fprintf(fp, "%2s %d\n\n", blk[(act[i] % item) * 10 / item],
		    act[i]);
	else
	    fprintf(fp, "%2s %d\n", blk[(act[i] % item) * 10 / item],
		    act[i]);
    }
    fclose(fp);
    return 0;
}
Пример #13
0
int main(int argc, char **argv)
{
    int i,serverid=0;
    FILE *fp=NULL,*fpscript=fopen(INND_SCRIPT,"w");
    char buf[256],serverstr[30]="";
    chdir(BBSHOME "/innd");
    attach_SHM();
    resolve_boards();
    memset(istran,0,sizeof(int)*MAX_BOARD);
    load_server();
    load_newsfeeds();

    for(i=0;i<feedcount;i++)
	{
	  if(strcasecmp(serverstr,feedline[i].server))
	   {
	     if(get_server(feedline[i].server)==-1) continue;
	     if(fp) {
			fclose(fp);	
                        dobbsnnrp(serverstr,serverid,fpscript);
		    }
	     strcpy(serverstr,feedline[i].server);
	     serverid=get_server(feedline[i].server);
	     sprintf(buf,INNDHOME"/active/%s.auto.active",serverstr);
	     fp=fopen(buf,"w");
	   }
          if(fp)
             fprintf(fp,"%-35s 0000000000 0000000000 y\r\n",feedline[i].group);
	}
    if(fp) 
    {
      dobbsnnrp(serverstr,serverid,fpscript);
      fclose(fp);
    }
    if(fpscript)
     {
	fclose(fpscript);
	chmod(INND_SCRIPT,0744);
     }

    // 重設轉信與不轉信板標記
    int total = num_boards();
    for(i=0;i<total;i++)
     {
       if(bcache[i].brdname[0]=='\0' ||
	   (bcache[i].brdattr & BRD_GROUPBOARD) ) continue;
       if((bcache[i].brdattr & BRD_NOTRAN )&& istran[i])
         {
	   while(SHM->Bbusystate) {safe_sleep(1);}
  	   SHM->Bbusystate = 1;
           bcache[i].brdattr = bcache[i].brdattr & ~BRD_NOTRAN;
           strncpy(bcache[i].title + 5, "●", 2);
	   SHM->Bbusystate = 0;

           substitute_record(BBSHOME"/.BRD", &bcache[i],sizeof(boardheader_t),i+1);
	 }
       else if(!(bcache[i].brdattr & BRD_NOTRAN) && !istran[i]) 
         {
	   while(SHM->Bbusystate) {safe_sleep(1);}
           SHM->Bbusystate = 1;
           bcache[i].brdattr = bcache[i].brdattr | BRD_NOTRAN;
           strncpy(bcache[i].title + 5, "◎", 2);
           SHM->Bbusystate = 0;
           substitute_record(BBSHOME"/.BRD", &bcache[i],sizeof(boardheader_t),i+1);
	 }

     }
    return 0;
}
Пример #14
0
int
main(void)
{
    FILE  *fp, *ftmp;
    int   i = 0, num;
    // char  *currboard[3] = {"CCK-CHUHEN", "CCK-GENERAL", "CCK-FREE"};
    // char  *kingdom[3] = {"·¡º~¬Ó´Â", "±N«Ó«ÒÁp", "³p»»¤ý´Â"};
    char  file1[80], file2[80], line[256], str[256];
    time_t dtime;
    boardheader_t brd;
    int brdfd;

    setgid(BBSGID);
    setuid(BBSUID);
    chdir(BBSHOME);  

    attach_SHM();

    time(&dtime);

    if ((brdfd = open(BBSHOME "/" FN_BOARD, O_RDONLY)) == -1){
	perror("open " BBSHOME "/" FN_BOARD);
	return 0;
    }
    
    while(read(brdfd, &brd, sizeof(brd)) == sizeof(brd))
    {
	const char* photo_fname = 0;
	const char* chess_name = 0;
	char kingdom_name[256];
	int bid;
	// struct stat st;

	switch(brd.chesscountry){
	    case CHESSCODE_FIVE:
		photo_fname = "photo_fivechess";
		chess_name = "¤­¤l´Ñ";
		break;
	    case CHESSCODE_CCHESS:
		photo_fname = "photo_cchess";
		chess_name = "¶H´Ñ";
		break;
	    case CHESSCODE_GO:
		photo_fname = "photo_go";
		chess_name = "³ò´Ñ";
		break;
	    case CHESSCODE_REVERSI:
		photo_fname = "photo_reversi";
		chess_name = "¶Â¥Õ´Ñ";
		break;
	    default:
		continue;
	}
	bid = getbnum(brd.brdname);

	setapath(str, brd.brdname);
	sprintf(file1, "%s/chess_list", str);

	printf("apath = %s\n", str);

	/*
	if (stat(file1, &st) == 0 && st.st_mtime > (dtime - UPDATE_FREQUENCY * 60))
	    continue;
	*/

	sprintf(file2, "%s/chess_list.tmp", str);
	if ((ftmp = fopen(file2, "w")) == NULL)
	    continue;

	if ((fp = fopen(file1, "r")))
	{
	    char  *p;
	    char userid[IDLEN + 1], buf[256], name[11];
	    char date[11], other[IDLEN + 1];
	    int  namelen;

	    fgets(kingdom_name, 256, fp);
	    fputs(kingdom_name, ftmp);
	    chomp(kingdom_name);
	    while (fgets(buf, sizeof(buf), fp))
	    {
		i = 0;
		strcpy(line, buf);
		p = strtok(buf, " ");
		name[0] = '\0';
		if (p && *p != '#' && searchuser(p, userid))
		{
		    i = 1;

		    if ((p = strtok(NULL, " ")))
			strlcpy(name, p, sizeof(name));
		    else
			i = 0;

		    if ((p = strtok(NULL, " ")))
			strlcpy(date, p, sizeof(date));
		    else
			i = 0;

		    if ((p = strtok(NULL, " ")))
			strlcpy(other, p, sizeof(other));
		    else
			i = 0;
		}
		if (!strcmp("°£¦W", name))
		{
		    sethomefile(buf, userid, photo_fname);
		    unlink(buf);
		    continue;
		}
		if (i == 0)
		{
		    fprintf(ftmp, "%s", line);
		    continue;
		}
		namelen = strlen(name);

		setapath(str, brd.brdname);
		sprintf(buf, "%s/chess_photo/.DIR", str);
		num = get_num_records(buf, sizeof(fileheader_t));
		for (i = 1; i <= num; i++)
		{
		    fileheader_t item;
		    if (get_record(buf, &item, sizeof item, i) != -1)
		    {
			FILE *fp1;
			if (!strncmp(item.title + 3, name, namelen) &&
				(item.title[namelen + 3] == '\0' ||
				 item.title[namelen + 3] == ' ')
				)
			{
			    sethomefile(buf, userid, photo_fname);
			    if ((fp1 = fopen(buf, "w")))
			    {
				sprintf(buf, "%s/chess_photo/%s", str, item.filename);
				f_suck6(fp1, buf);
				fprintf(fp1, "%d\n", bid);
				if (strcmp("«R¸¸", name))
				    fprintf(fp1, "<©ÒÄݤý°ê> %s (%s)\n", kingdom_name, chess_name);
				else
				    fprintf(fp1, "<«R¸¸¤ý°ê> %s\n", kingdom_name);
				fprintf(fp1, "<²{¦b¶¥¯Å> %s\n", name);
				fprintf(fp1, "<¥[¤J¤é´Á> %s\n", date);
				if (strcmp("«R¸¸", name))
				{
				    int level;
				    fprintf(fp1, "<¤ý°êµ¥¯Å> ");
				    level = atoi(other);
				    for (i = 0; i < level; i++)
					fprintf(fp1, "%s", "¡¹");
				}
				else
				{
				    chomp(other);
				    fprintf(fp1, "<³Q½Ö«R¸¸> %s", other);
				}
				fprintf(fp1, "\n<¦Û§Ú»¡©ú> \n");
				fclose(fp1);
			    }
			    break;
			}
		    }
		}
		if (i > num) // level photo not found
		    fprintf(ftmp, "%s", line);
		else
		    fprintf(ftmp, "#%s", line);
	    }
	    fclose(fp);
	    fclose(ftmp);
	    rename(file2, file1);
	} else {
	    fclose(ftmp);
	}
    }
    return 0;
}
Пример #15
0
int main(int argc, char *argv[])
{
    int fd;
    angel_beats_data req = {0};
    angel_beats_report rpt = {0};
    angel_beats_uid_list list = {0};
    attach_SHM();

    if (argc < 2) {
	fprintf(stderr, "Usage: %s operation [uid]\n", argv[0]);
	return 0;
    }
    if ( (fd = toconnect(ANGELBEATS_ADDR)) < 0 ) {
	perror("toconnect");
	return 1;
    }

    // start commands
    if (strcmp(argv[1], "reload") == 0) {
        req.operation = ANGELBEATS_REQ_RELOAD;
    } else if (strcmp(argv[1], "suggest") == 0) {
        req.operation = ANGELBEATS_REQ_SUGGEST;
        if (argc > 2) {
            req.operation = ANGELBEATS_REQ_SUGGEST_AND_LINK;
            req.master_uid = searchuser(argv[2], NULL);
        }
    } else if (strcmp(argv[1], "unlink") == 0) {
        if (argc != 3) {
            printf("need target id.\n");
            return -1;
        }
        req.operation = ANGELBEATS_REQ_REMOVE_LINK;
        req.master_uid = 0; // anyone, just unlink
        req.angel_uid = searchuser(argv[2], NULL);
        if (!req.angel_uid) {
            printf("invalid user id: %s\n", argv[2]);
            return -1;
        }
    } else if (strcmp(argv[1], "report") == 0) {
        req.operation = ANGELBEATS_REQ_REPORT;
        if (argc > 2 && !(req.angel_uid = searchuser(argv[2], NULL))) {
            printf("invalid user id: %s\n", argv[2]);
            return -1;
        }
    } else if (strcmp(argv[1], "list") == 0) {
        req.operation = ANGELBEATS_REQ_GET_ONLINE_LIST;
    } else if (strcmp(argv[1], "save") == 0) {
        req.operation = ANGELBEATS_REQ_SAVE_STATE;
    } else if (strcmp(argv[1], "perf") == 0) {
        req.operation = ANGELBEATS_REQ_EXPORT_PERF;
    } else {
        fprintf(stderr, "Sorry, unknown command: %s\n", argv[1]);
	return 0;
    }

    req.cb = sizeof(req);
    if (towrite(fd, &req, sizeof(req)) != sizeof(req)) {
	perror("towrite");
	return 1;
    }
    if (req.operation == ANGELBEATS_REQ_REPORT) {
        if (toread(fd, &rpt, sizeof(rpt)) != sizeof(rpt)) {
            perror("toread");
            return 1;
        }
        assert(rpt.cb == sizeof(rpt));
        printf("total_angels=%d\n"
               "total_online_angels=%d\n"
               "total_active_angels=%d\n"
               "min_masters_of_online_angels=%d\n"
               "max_masters_of_online_angels=%d\n"
               "min_masters_of_active_angels=%d\n"
               "max_masters_of_active_angels=%d\n"
               "my_index=%d\n"
               "my_active_index=%d\n"
               "my_active_masters=%d\n",
               rpt.total_angels,
               rpt.total_online_angels,
               rpt.total_active_angels,
               rpt.min_masters_of_online_angels,
               rpt.max_masters_of_online_angels,
               rpt.min_masters_of_active_angels,
               rpt.max_masters_of_active_angels,
               rpt.my_index,
               rpt.my_active_index,
               rpt.my_active_masters);
    } else if (req.operation == ANGELBEATS_REQ_GET_ONLINE_LIST) {
        int i;
        if (toread(fd, &list, sizeof(list)) != sizeof(list)) {
            perror("toread");
            return 1;
        }
        assert(list.cb == sizeof(list));
        printf("angels=%d\n", list.angels);
        for (i = 0; i < list.angels; i++) {
            printf("%3d. %s\n", i + 1, getuserid(list.uids[i]));
        }
    } else {
        if (toread(fd, &req, sizeof(req)) != sizeof(req)) {
            perror("toread");
            return 1;
        }
        printf("result: angel_uid=%d\n", req.angel_uid);
    }

    return 0;
}
Пример #16
0
int main(int argc, char *argv[])
{
    int bmid, i, j=0;
    FILE *inf, *firef;
    time4_t now=time(NULL); 
    attach_SHM();
    resolve_boards();

    if(passwd_init())
	exit(1);      

    memcpy(allbrd,bcache,numboards*sizeof(boardheader_t));

    /* write out the target file */
    inf   = fopen(OUTFILE, "w+");
    if (inf == NULL) {
	printf("open file error : %s\n", OUTFILE);
	exit(1);
    }

    firef = fopen(FIREFILE, "w+");
    if (firef == NULL) {
	printf("open file error : %s\n", FIREFILE);
	exit(1);
    }

    fprintf(inf, "警告: 板主若超過(不包含) %d天未上站,將予於免職\n",
            LAZY_BM_LIMIT_DAYS);
    fprintf(inf,
	    "看板名稱                                           "
	    "    板主        幾天沒來啦\n"
	    "---------------------------------------------------"
	    "--------------------------\n");

    fprintf(firef, "免職板主\n");
    fprintf(firef,
	    "看板名稱                                           "
	    "    板主        幾天沒來啦\n"
	    "---------------------------------------------------"
	    "--------------------------\n"); 


    j = 0;
    for (i = 0; i < numboards; i++) {
	char *p, bmbuf[IDLEN * 3 + 3];
	int   index = 0, flag = 0, k, n;
	userec_t xuser;
	p = allbrd[i].BM;

	if (*p == '[') p++;
	if (allbrd[i].brdname[0] == '\0' ||
		!isalpha(allbrd[i].brdname[0])
	   ) continue;

	p = strtok(p,"/ ]");
	for(index=0; p && index<5; index++) {
	    int diff;
	    // XXX what if bmid is invalid?
	    if(!p[0] || (bmid = passwd_load_user(p, &xuser)) < 1) {
		index--;
		p=strtok(NULL,"/ ]");
		continue;
	    }
	    strlcpy(bms[index].bmname, p, sizeof(bms[index].bmname));
	    bms[index].flag = 0;

	    diff = now - xuser.lastlogin;
	    if (diff < 0)
		diff = 0;

	    if (diff >= 45 * 86400
		    && !(xuser.userlevel & PERM_SYSOPHIDE)
		    && !(xuser.userlevel & PERM_SYSOP)) {
		strlcpy(lostbms[j].bmname, p, sizeof(bms[index].bmname));
		lostbms[j].title = allbrd[i].brdname;
		lostbms[j].ctitle = allbrd[i].title;
		lostbms[j].lostdays = diff / 86400;

		//超過 LAZY_BM_LIMIT_DAYS 天 免職
		if (lostbms[j].lostdays > LAZY_BM_LIMIT_DAYS) {
		    xuser.userlevel &= ~PERM_BM;
		    bms[index].flag = 1;
		    flag = 1;
                    // NOTE: 好像不改也無所謂,目前拔 BM 是自動的。
		    passwd_update(bmid, &xuser);
		}
		j++;
	    }
	    p = strtok(NULL,"/ ]");
	}

	if (flag == 1) {
            boardheader_t *bp = getbcache(i+1);

            // 確認我們沒搞錯 cache. 如果 cache 炸了就別用了
            if (strcmp(bp->brdname, allbrd[i].brdname) != 0) {
                printf("ERROR: unmatched cache!!! (%s - %s)\n",
                        bp->brdname, allbrd[i].brdname);
                bp = NULL;
                exit(1);
                // sync to latest
                memcpy(&allbrd[i], bp, sizeof(boardheader_t));
            }

	    bmbuf[0] = '\0';
	    for (k = 0, n = 0; k < index; k++) {
		if (!bms[k].flag) {
		    if (n++ != 0) strcat(bmbuf, "/");
		    strcat(bmbuf, bms[k].bmname);
		}
	    }
	    strcpy(allbrd[i].BM, bmbuf);
            printf("board %s: %s -> %s\n",
                    allbrd[i].brdname, bp->BM, allbrd[i].BM);
            strcpy(bp->BM, allbrd[i].BM);
	    if (substitute_record(BBSHOME"/"FN_BOARD, &allbrd[i], 
			sizeof(boardheader_t), i+1) == -1) {
		printf("Update Board Failed: %s\n", allbrd[i].brdname);
	    }
	    reset_board(i+1);
	}
    }
    qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp);

    //write to the etc/toplazyBM
    for (i = 0; i < j; i++) {
	if (lostbms[i].lostdays > LAZY_BM_LIMIT_DAYS) {
	    fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d天沒上站\n",
		    IDLEN, IDLEN, lostbms[i].title, BTLEN-10,
		    BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
		    lostbms[i].bmname,lostbms[i].lostdays);
	} else {
	    fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d天沒上站\n",
		    IDLEN, IDLEN, lostbms[i].title, BTLEN-10,
		    BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
		    lostbms[i].bmname,lostbms[i].lostdays);
	}
    }
    fclose(inf);
    fclose(firef);

    //printf("Total %d boards.\n", count);

    //mail to the users
    for (i=0; i<j; i++) {
	fileheader_t mymail;
	char	genbuf[200];
	int	lostdays;

	lostdays = lostbms[i].lostdays;

	if (lostdays != LAZY_BM_LIMIT_DAYS/2 &&
            lostdays != LAZY_BM_LIMIT_DAYS*2/3 &&
            lostdays != LAZY_BM_LIMIT_DAYS*5/6 &&
            lostdays <= LAZY_BM_LIMIT_DAYS)
	    continue;

	sprintf(genbuf, BBSHOME "/home/%c/%s", 
		lostbms[i].bmname[0], lostbms[i].bmname);
	stampfile(genbuf, &mymail);

	strcpy(mymail.owner, "[" BBSMNAME "警察局]");
	if (lostdays <= LAZY_BM_LIMIT_DAYS)
	    sprintf(mymail.title,
		    ANSI_COLOR(32) "版主通知" ANSI_RESET " %s版版主%s",
		    lostbms[i].title, lostbms[i].bmname);
	else
	    sprintf(mymail.title,
		    ANSI_COLOR(32) "版主自動免職通知" ANSI_RESET " %s 版主 %s",
		    lostbms[i].title, lostbms[i].bmname);

	unlink(genbuf);
	if (lostdays <= LAZY_BM_LIMIT_DAYS)
	    Link(OUTFILE, genbuf);
	else
	    Link(FIREFILE, genbuf);

	sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", 
		lostbms[i].bmname[0], lostbms[i].bmname);
	append_record(genbuf, &mymail, sizeof(mymail)); 	
    }
    return 0;
}