src/build_history.c

/* [<][>]
[^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. getdirname
  2. fullpath
  3. scan_article
  4. scan_directory
  5. build_history

/* $Id: build_history.c,v 1.1.1.1 1998/07/29 15:14:29 proff Exp $
 * $Copyright$
 */

#include "nglobal.h"
#include "filesystem.h"
#include "history.h"

#include "build_history.h"

/* Strip off the port numbers to get the directory name. */
static char *getdirname(char *host)
/* [<][>][^][v][top][bottom][index][help] */
{
        char *p, *q;

        p = Sstrdup(host);
        q = strchr(p, ':');
        if (q) *q = 0;
        return p;
}

/* Form the "full" pathname of a file. */
static char *fullpath(char *path, char *d_name)
/* [<][>][^][v][top][bottom][index][help] */
{
        char *p;
        int path_len, d_name_len;
        int len;

        path_len = strlen(path);
        d_name_len = strlen(d_name);
        len = path_len + d_name_len + 2;
        p = Smalloc(len);
        memcpy(p, path, path_len);
        p[path_len] = '/';
        memcpy(p + path_len + 1, d_name, d_name_len);
        p[len - 1] = 0;
        return p;
}

/* Scan one article and add it to the history if necessary. */
static void scan_article(char *path, char *artno)
/* [<][>][^][v][top][bottom][index][help] */
{
        FILE *fp;
        char buf[MAX_HEADER];
        char msgid[MAX_MSGID] = "";

        if (!(fp = fopen(artno, "r"))) {
                loge(("couldn't open '%s' for history rebuild", artno));
                return;
        }

        while (!*msgid && fgets(buf, sizeof(buf), fp)) {
                if (tolower(*buf) == 'm' &&
                    strnCaseEq(buf, "message-id:", 11)) {

                                if (strSnip (buf+11, sizeof buf, "<", ">\n\r", msgid, sizeof msgid) > 0) {
                                        if (!hisGetDbz(msgid))
                                                hisAddDbz(msgid, path);
                                }
                                break;
                        }
                while (buf[strlen(buf) - 1] != '\n' &&
                        fgets(buf, sizeof(buf), fp));
        }
        fclose(fp);
}

/* Scan the current directory recursively for things to add to the history. */
static void scan_directory(char *path)
/* [<][>][^][v][top][bottom][index][help] */
{
        DIR *dp;
        struct dirent *ep;
        char *p, *q;
        int i;
        struct stat st;

        if (!(dp = opendir(path))) {
                loge(("rebuild: opendir('%s') failed", path));
                return;
        }

        while ((ep = readdir(dp))) {
                q = ep->d_name;
                p = fullpath(path, q);
                if (stat(p, &st) < 0) {
                        loge(("rebuild: stat('%s') failed", p));
                        free(p);
                        continue;
                }

                if (*q == '.')
                        ;
                else if (S_ISDIR(st.st_mode)) scan_directory(p);
                else {
                        i = strspn(q, "0123456789");
                        if (S_ISREG(st.st_mode) && isdigit(q[0]) &&
                                (!q[i] || q[i] == '_')) {
                                if (q[i] == '_') q[i] = 0;
                                q = fullpath(path, q);
                                scan_article(q, p);
                        }
                }
                free(p);
        }
        closedir(dp);
}

/* Build the history file. */
EXPORT void build_history()
/* [<][>][^][v][top][bottom][index][help] */
{
        char *p;
        struct server_cfg *scfg;

        for (scfg = ServerList; scfg; scfg = scfg->next) {
                if (chdir(con->cacheDir)) {
                        loge(("rebuild: unable to chdir('%s')", con->cacheDir));
                        return;
                }
                p = getdirname(scfg->host);
                scan_directory(p);
                free(p);
        }
}

/* [<][>][^][v][top][bottom][index][help] */