/* $Id$ */ /* 'mandex -h' to help */ #include "bbs.h" #ifndef MAXPATHLEN #define MAXPATHLEN 1024 #endif typedef struct { char bname[40]; int ndir, nfile, k; } boardinfo; extern int numboards; extern boardheader_t *bcache; boardinfo board[MAX_BOARD], *biptr; char color[4][10] = {"", "", "", ""}; char fn_index[] = ".index"; char fn_new[] = ".index.new"; char index_title[] = "◎ 精華區目錄索引"; char topdir[128], pgem[512], pndx[512]; FILE *fndx; int ndir, nfile, index_pos, k; int nSorted, nb; int sortbyname(const void *a, const void *b) { return strcmp(((boardinfo*)b)->bname, ((boardinfo*)a)->bname); } int k_cmp(b, a) boardinfo *b, *a; { return ((a->k / 100 + a->ndir + a->nfile) - (b->k / 100 + b->ndir + b->nfile)); } /* visit the hierarchy recursively */ void mandex(level, num_header, fpath) int level; char *fpath, *num_header; { FILE *fgem; char *fname, buf[256]; struct stat st; int count; fileheader_t fhdr; fgem = fopen(fpath, "r+"); if (fgem == NULL) return; fname = strrchr(fpath, '.'); if (!level){ printf("%s\r\n",fpath); strcpy(pgem, fpath); strcpy(fname, fn_new); fndx = fopen(fpath, "w"); if (fndx == NULL){ fclose(fgem); return; } fprintf(fndx, "序號\t\t\t精華區主題\n" "───────────────────" "───────────────────\n"); strcpy(pndx, fpath); ndir = nfile = 0; index_pos = -1; } count = 0; while (fread(&fhdr, sizeof(fhdr), 1, fgem) == 1){ strcpy(fname, fhdr.filename); if (!fname[0]) continue; if (!level && !strncmp(fhdr.title, index_title, strlen(index_title)) && index_pos < 0){ index_pos = count; unlink(fpath); } st.st_size = 0; stat(fpath, &st); sprintf(buf, "%.*s%s%3d. %s \n", 11 * level, num_header, color[level % 4], ++count, fhdr.title); /* Ptt */ fputs(buf, fndx); if (dashd(fpath)){ ++ndir; /* I can't find the code to change title? */ if (*fhdr.title != '#' && level < 10 && (fhdr.filemode&(FILE_BM|FILE_HIDE))==0){ strcat(fpath, "/.DIR"); mandex(level + 1, buf, fpath); } } else ++nfile; } if (!level){ char lpath[MAXPATHLEN]; fclose(fndx); strcpy(fname, fn_index); rename(pndx, fpath); strcpy(pndx, fpath); sprintf(buf, "%s.new", pgem); if (index_pos >= 0 || (fndx = fopen(buf, "w"))){ fname[-1] = 0; stamplink(fpath, &fhdr); unlink(fpath); strcpy(fhdr.owner, "每天自動更新"); sprintf(lpath, "%s/%s", topdir, pndx); st.st_size = 0; stat(lpath, &st); sprintf(fhdr.title, "%s (%.1fk)", index_title, st.st_size / 1024.); k = st.st_size; /* Ptt */ printf("(%s)[%dK]", fpath, k); symlink(lpath, fpath); if (index_pos < 0){ fwrite(&fhdr, sizeof(fhdr), 1, fndx); rewind(fgem); while (fread(&fhdr, sizeof(fhdr), 1, fgem) == 1) fwrite(&fhdr, sizeof(fhdr), 1, fndx); fclose(fndx); fclose(fgem); rename(buf, pgem); } else{ fseek(fgem, index_pos * sizeof(fhdr), 0); fwrite(&fhdr, sizeof(fhdr), 1, fgem); fclose(fgem); } return; } } fclose(fgem); } int main(int argc, char* argv[]) { boardheader_t *bptr = NULL; DIR *dirp; struct dirent *de; int ch, n, place = 0, fd, i; char checkrebuild = 0, *fname, fpath[MAXPATHLEN]; char dirs[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', 0}; nice(10); while( (ch = getopt(argc, argv, "xh")) != -1 ){ switch( ch ){ case 'x': checkrebuild = 1; break; case 'h': printf("NAME \n" " mandex - 精華區索引程式 (man index)\n\n" "SYNOPSIS \n" " mandex [-x] [board] \n\n" "DESCRIPTION \n" "精華區索引 (man index) \n\n" "-x 只有含有 .rebuild的目錄才重製 \n" "board 全部的板 (default to all) \n\n"); return 0; } } argc -= optind; argv += optind; attach_SHM(); resolve_boards(); /* if( argc == 0 ){ puts("Creating the whole index..."); chdir(strcpy(topdir, BBSHOME)); strcpy(fpath, "man/.DIR"); mandex(0, "", fpath); } */ chdir(strcpy(topdir, BBSHOME "/man/boards")); if( argc == 1 ){ sprintf(fpath, "%c/%s/.DIR", argv[0][0], argv[0]); mandex(0, "", fpath); return 0; } /* process all boards */ if( checkrebuild && (fd = open(BBSHOME "/man/.rank.cache", O_RDONLY)) >= 0 ){ read(fd, board, sizeof(board)); close(fd); qsort(board, MAX_BOARD, sizeof(boardinfo), sortbyname); for( nb = 0 ; board[nb].bname[0] != 0 ; ++nb ) ; nSorted = nb; } else{ memset(board, 0, sizeof(board)); checkrebuild = 0; nSorted = nb = 0; } for( i = 0 ; dirs[i] != 0 ; ++i ){ sprintf(topdir, BBSHOME "/man/boards/%c", dirs[i]); chdir(topdir); if(!(dirp = opendir(topdir))) { printf("## unable to enter [man/boards]\n"); exit(-1); } while((de = readdir(dirp))){ fname = de->d_name; ch = fname[0]; if (ch != '.'){ k = 0; if( checkrebuild ){ sprintf(fpath, "%s/.rebuild", fname); if( access(fpath, 0) < 0 ){ printf("skip no modify board %s\n", fname); continue; } unlink(fpath); } sprintf(fpath, "%s/.DIR", fname); mandex(0, "", fpath); printf("%-14sd: %d\tf: %d\n", fname, ndir, nfile); /* report */ if( k ){ if( !(biptr = bsearch(fname, board, nSorted, sizeof(boardinfo), sortbyname))){ biptr = &board[nb]; ++nb; } strcpy(biptr->bname, fname); biptr->ndir = ndir; biptr->nfile = nfile; biptr->k = k; } } } closedir(dirp); } qsort(board, nb, sizeof(boardinfo), k_cmp); unlink(BBSHOME "/man/.rank.cache"); if( (fd = open(BBSHOME "/man/.rank.cache", O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0660)) >= 0 ){ write(fd, board, sizeof(board)); close(fd); } if (!(fndx = fopen(BBSHOME "/etc/topboardman", "w"))) exit(0); fprintf(fndx, "排名 看 板 目錄數 檔案數" " byte數  總 分 板 主 \n"); for (ch = 0; ch < nb; ch++){ for (n = 0; n < numboards; n++){ bptr = &bcache[n]; if (!strcmp(bptr->brdname, board[ch].bname)) break; } if (n >= numboards || (bptr->brdattr & (BRD_BAD | BRD_NOCOUNT))) continue; /* 板主設定不列入記錄 */ if (bptr->brdattr & BRD_HIDE && !(bptr->brdattr & BRD_BMCOUNT)) continue; if (board[ch].ndir + board[ch].nfile < 5) break; fprintf(fndx, "%3d.%15s %5d %7d %10d %6d %-24.24s\n", ++place, board[ch].bname, board[ch].ndir, board[ch].nfile, board[ch].k ,board[ch].k / 100 + board[ch].nfile + board[ch].ndir ,bptr->BM); } fclose(fndx); return 0; }