summaryrefslogblamecommitdiffstats
path: root/util/mandex.c
blob: eb8de895abad192731796df01542eefbd3daf608 (plain) (tree)
1
2
3
4
5
6
7
8
9
          
 
                         
 
                
 
                
                   
                       





                                                                           


                                            
                                                                      
 
 
                                       
 
                                                                   


                                                                                   

                                
 
                                     
    
                                                            
 

                          


                      
                                             

               




                                                        
 

                              
 

                                               
 

                                                                             
                                                                               





                                                                       



                                              
                                 

     










                                          
                              

















































                                                                                                  
         






















                                                                                            
     


                     

 





































                                                                                  








                                                         
 

                                
                       
                        

                       

                                    
 
             

















                                                                   





                   

                   
                 
                     
 




                                           
                 


                            
                                                                        

                                       

                                                                 
                     
            



                                        
 



                                                                    

                     
    
                                      
                               




                                
                                                                            


                                                               
                 








                                                                                               

             
                       
     
    

                                                 
                                       



                                                                          

                  
 
             
 
/* $Id$ */

/* 'mandex -h' to help */

#include "bbs.h"

typedef struct {
    char bname[40];
    int ndir, nfile, k;
} boardinfo_t;

static const char *color[4] = {"", "", "", ""};
static const char *fn_index = ".index";
static const char *fn_new = ".index.new";
static const char *index_title = "◎ 精華區目錄索引";;

int sortbyname(const void *a, const void *b)
{
    return strcmp(((boardinfo_t*)b)->bname, ((boardinfo_t*)a)->bname);
}

int k_cmp(const void *x, const void *y)
{
    const boardinfo_t *b = (boardinfo_t *)x, *a = (boardinfo_t *)y;
    return ((a->k / 100 + a->ndir + a->nfile) - (b->k / 100 + b->ndir + b->nfile));
}

static FILE *fp_index;
static boardinfo_t curr_brdinfo;

/* visit the hierarchy recursively */
void
mandex(const int level, const char *num_header, char *fpath)
{
    FILE *fp_dir;
    char *fname, buf[512];
    int count;
    fileheader_t fhdr;

    if ((fp_dir = fopen(fpath, "r")) == NULL)
    return;

    fname = strrchr(fpath, '/') + 1;
    count = 0;

    while (fread(&fhdr, sizeof(fhdr), 1, fp_dir) == 1) {
    ++count;

    if (!fhdr.filename[0])
        continue;

    *fname = '\0';
    strlcat(fpath, fhdr.filename, PATHLEN);

    snprintf(buf, sizeof(buf), "%.*s%s%3d. %s \n",
        11 * level, num_header, color[level % 4], count, fhdr.title);
                                                                  /* Ptt */
    fputs(buf, fp_index);

    if (dashd(fpath)) {
        curr_brdinfo.ndir++;
        if (level < 10 && !(fhdr.filemode & (FILE_BM|FILE_HIDE))) {
        strlcat(fpath, "/" FN_DIR, PATHLEN);
        mandex(level + 1, buf, fpath);
        }
    }
    else
        curr_brdinfo.nfile++;
    }

    fclose(fp_dir);
}

void
man_index(const char * brdname)
{
    char buf[PATHLEN], fpath[PATHLEN], *p;
    int i, index_pos = -1;
    FILE *fp_dir;
    struct stat st;
    fileheader_t fhdr;
    const boardheader_t *bptr;

    if ((i = getbnum(brdname)) == 0)
    return;

    bptr = getbcache(i);
    if (strcmp(brdname, bptr->brdname) != 0)
    return;

    memset(&curr_brdinfo, 0, sizeof(curr_brdinfo));
    strlcpy(curr_brdinfo.bname, brdname, sizeof(curr_brdinfo.bname));

    setapath(buf, brdname);
    setadir(fpath, buf);

    setdirpath(buf, fpath, fn_new);

    if ((fp_index = fopen(buf, "w")) == NULL)
    return;

    fprintf(fp_index, "序號\t\t\t精華區主題\n"
        "───────────────────"
        "───────────────────\n");
    printf("%s ", fpath);
    mandex(0, "", fpath);
    fclose(fp_index);
    stat(buf, &st);
    curr_brdinfo.k = st.st_size;
    printf("(%s)[%dK] d: %d f: %d\n", buf, curr_brdinfo.k, curr_brdinfo.ndir, curr_brdinfo.nfile);

    setdirpath(fpath, buf, fn_index);
    rename(buf, fpath);
    setdirpath(fpath, buf, FN_DIR);

    sprintf(buf, "%s.new", fpath);

    if ((fp_dir = fopen(fpath, "r+")) == NULL)
    return;

    if ((fp_index = fopen(buf, "w")) == NULL) {
    fclose(fp_dir);
    return;
    }

    i = 0;
    while (fread(&fhdr, sizeof(fhdr), 1, fp_dir) == 1) {
    if (strncmp(fhdr.title, index_title, strlen(index_title)) == 0) {
        index_pos = i;
        setdirpath(buf, fpath, fhdr.filename);
        unlink(buf);
        break;
    }
    i++;
    }

    p = strrchr(buf, '/');
    *p = '\0';
    stamplink(buf, &fhdr);
    unlink(buf);
    symlink(fn_index, buf);
    strlcpy(fhdr.owner, "每天自動更新", sizeof(fhdr.owner));
    snprintf(fhdr.title, sizeof(fhdr.title), "%s (%.1fk)", index_title, st.st_size / 1024.);

    sprintf(buf, "%s.new", fpath);

    if (index_pos >= 0) {
    fseek(fp_dir, index_pos * sizeof(fhdr), SEEK_SET);
    fwrite(&fhdr, sizeof(fhdr), 1, fp_dir);
    unlink(buf);
    } else {
    fwrite(&fhdr, sizeof(fhdr), 1, fp_index);
    rewind(fp_dir);
    while (fread(&fhdr, sizeof(fhdr), 1, fp_dir) == 1)
        fwrite(&fhdr, sizeof(fhdr), 1, fp_index);
    rename(buf, fpath);
    }

    fclose(fp_index);
    fclose(fp_dir);
}

void
output_chart(const boardinfo_t * board, const int nbrds)
{
    FILE * fp;
    int i, n, place = 0;
    boardheader_t *bptr = NULL;

    if (!(fp = fopen(BBSHOME "/etc/topboardman", "w")))
    return;

    fprintf(fp, "排名        看 板  目錄數   檔案數"
        "     byte數   總 分     板   主          \n");

    for (i = 0; i < nbrds; i++) {
    if ((n = getbnum(board[i].bname)) == 0)
        continue;

    bptr = getbcache(n);
    if (strcmp(board[i].bname, bptr->brdname) != 0)
        continue;

    if (bptr->brdattr & (BRD_BAD | BRD_NOCOUNT))
        continue;

    /* 板主設定不列入記錄 */
    if (bptr->brdattr & BRD_HIDE && !(bptr->brdattr & BRD_BMCOUNT))
        continue;

    if (board[i].ndir + board[i].nfile < 5)
        break;

    fprintf(fp, "%3d.%15s %5d %7d %10d   %6d %-24.24s\n",
        ++place, board[i].bname, board[i].ndir, board[i].nfile, board[i].k
        ,board[i].k / 100 + board[i].nfile + board[i].ndir
        ,bptr->BM);
    }
    fclose(fp);
}
static boardinfo_t board[MAX_BOARD];
static const char dirs[] = {
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
    'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
    'u', 'v', 'w', 'x', 'y', 'z',
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
    'U', 'V', 'W', 'X', 'Y', 'Z', 0};

int main(int argc, char* argv[])
{
    boardinfo_t *biptr;
    int     nSorted, nb;
    DIR     *dirp;
    struct  dirent *de;
    int     i, fd, checkrebuild = 0;
    char    *fname, fpath[PATHLEN];

    nice(10);
    while ((i = getopt(argc, argv, "xh")) != -1) {
    switch (i) {
        case 'x':
        checkrebuild = 1;
        break;
        case 'h':
        printf("NAME\n"
               "     mandex - 精華區索引程式 (man index)\n"
               "\n"
               "SYNOPSIS\n"
               "     mandex [-x] [-v] [board] ...\n"
               "\n"
               "DESCRIPTION\n"
               "精華區索引 (man index)\n\n"
               "-x    只有含有 .rebuild的目錄才重製\n"
               "-v    顯示全部路徑\n"
               "board 全部的板 (default to all)\n\n");
        return 0;
    }
    }

    argc -= optind;
    argv += optind;

    chdir(BBSHOME);

    attach_SHM();
    resolve_boards();

    /* process boards given in arguments */
    if (argc > 0) {
    for (i = 0; i < argc; i++)
        man_index(argv[i]);

    return 0;
    }

    /* process all boards */
    if (checkrebuild && (fd = open("man/.rank.cache", O_RDONLY)) >= 0) {
    read(fd, board, sizeof(board));
    close(fd);
    qsort(board, MAX_BOARD, sizeof(boardinfo_t), 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) {
    snprintf(fpath, sizeof(fpath), "man/boards/%c", dirs[i]);
    if (!(dirp = opendir(fpath))) {
        printf("## unable to enter [man/boards/%c]\n", dirs[i]);
        exit(-1);
    }
    
    while ((de = readdir(dirp))) {
        fname = de->d_name;

        if (fname[0] == '.')
        continue;

        if (checkrebuild) {
        sprintf(fpath, "man/boards/%c/%s/.rebuild", dirs[i], fname);
        if (access(fpath, 0) < 0) {
            printf("skip no modify board %s\n", fname);
            continue;
        }
        unlink(fpath);
        }

        man_index(fname);

        if (curr_brdinfo.k) {
        if (!(biptr = bsearch(fname, board, nSorted, sizeof(boardinfo_t), sortbyname)))
            biptr = &board[nb++];
        memcpy(biptr, &curr_brdinfo, sizeof(boardinfo_t));
        }
    }
    closedir(dirp);
    }
    
    qsort(board, nb, sizeof(boardinfo_t), k_cmp);
    output_chart(board, nb);
    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);
    }

    return 0;
}