summaryrefslogblamecommitdiffstats
path: root/upgrade/r4194_passwd.c
blob: fe555c4379e5a4e840dc1f516a0c32a96d308922 (plain) (tree)











































































































































































































































                                                                                   
                                                                    


























                                                                                        
#include "bbs.h"

int trans = 0;
int partial = 0;
int justified = 0;
int regformed = 0;

char * const str_space = " \t\n\r";


////////////////////////////////////////////////////////////////////////////
// Regform Utilities
////////////////////////////////////////////////////////////////////////////
#define FN_REGFORM "regform"
#define FN_REQLIST "reg.wait"

// TODO define and use structure instead, even in reg request file.
typedef struct {
    char userid[IDLEN+1];
    char name  [20];
    char career[40];
    char addr  [50];
    char phone [20];
} RegformEntry;

// regform format utilities
int
load_regform_entry(RegformEntry *pre, FILE *fp)
{
    char buf[STRLEN];
    char *v;

    memset(pre, 0, sizeof(RegformEntry));
    while (fgets(buf, sizeof(buf), fp))
    {
        if (buf[0] == '-')
            break;
        buf[sizeof(buf)-1] = 0;
        v = strchr(buf, ':');
        if (v == NULL)
            continue;
        *v++ = 0;
        if (*v == ' ') v++;
        chomp(v);

        if (strcmp(buf, "uid") == 0)
            strlcpy(pre->userid, v, sizeof(pre->userid));
        else if (strcmp(buf, "name") == 0)
            strlcpy(pre->name, v, sizeof(pre->name));
        else if (strcmp(buf, "career") == 0)
            strlcpy(pre->career, v, sizeof(pre->career));
        else if (strcmp(buf, "addr") == 0)
            strlcpy(pre->addr, v, sizeof(pre->addr));
        else if (strcmp(buf, "phone") == 0)
            strlcpy(pre->phone, v, sizeof(pre->phone));
    }
    return pre->userid[0] ? 1 : 0;
}

int
regfrm_load(const char *userid, RegformEntry *pre)
{
    FILE *fp = NULL;
    char fn[PATHLEN];
    int ret = 0;
    sethomefile(fn, userid, FN_REGFORM);
    if (!dashf(fn))
        return 0;

    fp = fopen(fn, "rt");
    if (!fp)
        return 0;
    ret = load_regform_entry(pre, fp);
    fclose(fp);
    return ret;
}

// working queue
FILE *
regq_init_pull()
{
    FILE *fp = tmpfile(), *src =NULL;
    char buf[STRLEN];
    if (!fp) return NULL;
    src = fopen(FN_REQLIST, "rt");
    if (!src) { fclose(fp); return NULL; }
    while (fgets(buf, sizeof(buf), src))
    fputs(buf, fp);
    fclose(src);
    rewind(fp);
    return fp;
}

int 
regq_pull(FILE *fp, char *uid)
{
    char buf[STRLEN];
    size_t idlen = 0;
    uid[0] = 0;
    if (fgets(buf, sizeof(buf), fp) == NULL)
    return 0;
    idlen = strcspn(buf, str_space);
    if (idlen < 1) return 0;
    if (idlen > IDLEN) idlen = IDLEN;
    strlcpy(uid, buf, idlen+1);
    return 1;
}

int
regq_end_pull(FILE *fp)
{
    // no need to unlink because fp is a tmpfile.
    if (!fp) return 0;
    fclose(fp);
    return 1;
}

void transform(userec_t *new, userec_t *old, int i)
{
    char fn[1024];
    char *s, *s2;
    memcpy(new, old, sizeof(userec_t));

    // already converted?
    if (old->version == PASSWD_VERSION || !old->userid[0])
    return;

    if (old->version != 2275 && old->userid[0])
    {
    fprintf(stderr, "invalid record at %d: %s\n", i, old->userid);
    if (i == 1)
        memset(new, 0, sizeof(userec_t));
    return;
    }

    // update version info
    new->version = PASSWD_VERSION;
    // zero out
    memset(new->career,  0, sizeof(new->career));
    memset(new->phone,   0, sizeof(new->phone));
    memset(new->chkpad0, 0, sizeof(new->chkpad0));
    memset(new->chkpad1, 0, sizeof(new->chkpad1));
    memset(new->chkpad2, 0, sizeof(new->chkpad2));

    // quick skip
    if (!old->justify[0] || !old->userid[0])
    return;

    printf("%s ", old->userid);
    printf("%s -> ", old->justify);

    s = old->justify;

    // process only if justify is truncated.
    while (strlen(old->justify) == sizeof(old->justify) -1)
    {
    RegformEntry re;

    // try regform first.
    if (regfrm_load(old->userid, &re)) {
        // trust the form.
        strlcpy(new->career, re.career, sizeof(new->career));
        strlcpy(new->phone,  re.phone,  sizeof(new->phone));
        // justify will be updated someday... throw it
        printf("<regq> [%s][%s][%s]\n", new->career, new->phone, new->justify);
        regformed ++;
        trans++;
        return;
    }

    // try to build from ~/justify, if exists.
    sethomefile(fn, old->userid, "justify");
    if (dashf(fn)) {
        FILE *fp = fopen(fn, "rt");
        fn[0] = 0;
        fgets(fn, sizeof(fn), fp);
        fclose(fp);
        chomp(fn);

        if (strlen(fn) > strlen(s))
        {
        char *xs;
        int quotes = 3;
        s = fn;
        // some justifies have multiple entries without \n...
        xs = s + strlen(s);
        while (quotes > 0 && xs > s)
            if (*--xs == ':')
            quotes--;
        if (xs > s)
            s = xs+1;

        justified ++;
        }
    }

    break;
    }

    // build career/phone
    s2 = strchr(s, ':');
    if (s2) {
    *s2++ = 0;
    while (*s && !isdigit(*s) && *s != '(') s++;
    strlcpy(new->phone,   s,  sizeof(new->phone));
    strlcpy(new->justify, s2, sizeof(new->justify));
    s = s2;
    s2 = strchr(s, ':');
    if (s2)
    {
        *s2++ = 0;
    }
    else if (new->userlevel & PERM_LOGINOK)
    {
        // skip non-loginOK users
        partial ++;
        printf(" <partial> ");
    }
    strlcpy(new->career, s, sizeof(new->career));
    if (s2)
        strlcpy(new->justify, s2, sizeof(new->justify));
    else
        strlcpy(new->justify, "", sizeof(new->justify));
    }
    printf("[%s][%s][%s]\n", new->career, new->phone, new->justify);

    trans++;
}

int main(void)
{
    int fd, fdw;
    userec_t new;
    userec_t old;
    int i = 0;

    printf("sizeof(userec_t)=%u\n", (unsigned int)sizeof(userec_t));
    printf("You're going to convert your .PASSWDS\n");
    printf("The new file will be named .PASSWDS.trans.tmp\n");

    if (chdir(BBSHOME) < 0) {
    perror("chdir");
    exit(-1);
    }

    if ((fd = open(FN_PASSWD, O_RDONLY)) < 0 ||
     (fdw = open(FN_PASSWD".trans.tmp", O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 ) {
    perror("open");
    exit(-1);
    }

    while (read(fd, &old, sizeof(old)) > 0) {
    transform(&new, &old, ++i);
    write(fdw, &new, sizeof(new));
    }

    close(fd);
    close(fdw);

    // TODO use FN_REQLIST to process other forms
    printf("total %d records translated (%d partial, %d justified, %d regformed).\n", 
        trans, partial, justified, regformed);
    return 0;
}