summaryrefslogblamecommitdiffstats
path: root/util/expire.c
blob: c0ebdd090a8220329c68667fd8f153ab0180e224 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
                                                       















                      
                  
















































































































































































































                                                                                           
/* $Id: expire.c,v 1.2 2002/03/09 17:44:30 in2 Exp $ */
/* 自動砍信工具程式 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include "config.h"
#include "pttstruct.h"
#include "util.h"
#include "proto.h"

#define QCAST int (*)(const void *, const void *)

#define DEF_DAYS    50
#define DEF_MAXP    2000
#define DEF_MINP    300

#define EXPIRE_CONF BBSHOME "/etc/expire.conf"
extern boardheader_t *bcache;
char *bpath = BBSHOME "/boards";

struct life
{
    char bname[16];     /* board ID */
    int days;           /* expired days */
    int maxp;           /* max post */
    int minp;           /* min post */
};
typedef struct life life;


void
 expire(brd)
life *brd;
{
    fileheader_t head;
    struct stat state;
    char lockfile[128], tmpfile[128], bakfile[128];
    char fpath[128], index[128], *fname;
    int total, bid;
    int fd, fdr, fdw, done, keep;
    int duetime, ftime;

    printf("%s\n", brd->bname);
    if((bid = getbnum(brd->bname)) == 0 || 
    strcmp(brd->bname, bcache[bid-1].brdname))
     {
        printf("no such board?: %s\n", brd->bname);    
        return;
     }
#ifdef  VERBOSE
    if (brd->days < 1)
    {
    printf(":Err: expire time must more than 1 day.\n");
    return;
    }
    else if (brd->maxp < 100)
    {
    printf(":Err: maxmum posts number must more than 100.\n");
    return;
    }
#endif

    sprintf(index, "%s/%s/.DIR", bpath, brd->bname);
    sprintf(lockfile, "%s.lock", index);
    if ((fd = open(lockfile, O_RDWR | O_CREAT | O_APPEND, 0644)) == -1)
    return;
    flock(fd, LOCK_EX);

    strcpy(fpath, index);
    fname = (char *) strrchr(fpath, '.');

    duetime = time(NULL) - brd->days * 24 * 60 * 60;
    done = 0;
    if ((fdr = open(index, O_RDONLY, 0)) > 0)
    {
    fstat(fdr, &state);
    total = state.st_size / sizeof(head);
    sprintf(tmpfile, "%s.new", index);
    unlink(tmpfile);
    if ((fdw = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0644)) > 0)
    {
        while (read(fdr, &head, sizeof head) == sizeof head)
        {
        done = 1;
        ftime = atoi(head.filename + 2);
        if (head.owner[0] == '-')
            keep = 0;
        else if (head.filemode & FILE_MARKED || total <= brd->minp)
            keep = 1;
        else if (ftime < duetime || total > brd->maxp)
            keep = 0;
        else
            keep = 1;

        if (keep)
        {
            if (write(fdw, (char *)&head, sizeof head) == -1)
            {
            done = 0;
            break;
            }
        }
        else
        {
            strcpy(fname, head.filename);
            unlink(fpath);
            printf("\t%s\n", fname);
            total--;
        }
        }
        close(fdw);
    }
    close(fdr);
    }

    if (done)
    {
    sprintf(bakfile, "%s.old", index);
    if (rename(index, bakfile) != -1)
         {
        rename(tmpfile, index);
        touchbtotal(bid);
         }
    }
    flock(fd, LOCK_UN);
    close(fd);
}


int main(argc, argv)
char *argv[];
{
    FILE *fin;
    int number, count;
    life db, table[MAX_BOARD], *key;
    struct dirent *de;
    DIR *dirp;
    char *ptr, *bname, buf[256];

    resolve_boards();
    db.days = ((argc > 1) && (number = atoi(argv[1])) > 0) ? number : DEF_DAYS;
    db.maxp = ((argc > 2) && (number = atoi(argv[2])) > 0) ? number : DEF_MAXP;
    db.minp = ((argc > 3) && (number = atoi(argv[3])) > 0) ? number : DEF_MINP;

/* --------------- */
/* load expire.ctl */
/* --------------- */

    count = 0;
    if((fin = fopen(EXPIRE_CONF, "r")))
    {
    while (fgets(buf, 256, fin))
    {
        if (buf[0] == '#')
        continue;

        bname = (char *) strtok(buf, " \t\r\n");
        if (bname && *bname)
        {
        ptr = (char *) strtok(NULL, " \t\r\n");
        if (ptr && (number = atoi(ptr)) > 0)
        {
            key = &(table[count++]);
            strcpy(key->bname, bname);
            key->days = number;
            key->maxp = db.maxp;
            key->minp = db.minp;

            ptr = (char *) strtok(NULL, " \t\r\n");
            if (ptr && (number = atoi(ptr)) > 0)
            {
            key->maxp = number;

            ptr = (char *) strtok(NULL, " \t\r\n");
            if (ptr && (number = atoi(ptr)) > 0)
            {
                key->minp = number;
            }
            }
        }
        }
    }
    fclose(fin);
    }

    if (count > 1)
    {
    qsort(table, count, sizeof(life), (QCAST)strcasecmp);
    }

/* ---------------- */
/* visit all boards */
/* ---------------- */

    if (!(dirp = opendir(bpath)))
    {
    printf(":Err: unable to open %s\n", bpath);
    return -1;
    }

    while((de = readdir(dirp)))
    {
    ptr = de->d_name;
    if (ptr[0] > ' ' && ptr[0] != '.')
    {
        if (count)
        key = (life *) bsearch(ptr, table, count, sizeof(life), (QCAST)strcasecmp);
        else
        key = NULL;
        if (!key)
        key = &db;
        strcpy(key->bname, ptr);
        expire(key);
    }
    }
    closedir(dirp);
    return 0;
}