summaryrefslogtreecommitdiffstats
path: root/util/uhash_loader.c
blob: 2d88dd06e5f68734c33b2334c45cba4f7cdafd13 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* $Id: uhash_loader.c,v 1.1 2002/03/07 15:13:47 in2 Exp $ */
/* standalone uhash loader -- jochang */
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#ifdef __FreeBSD__
#include <machine/param.h>
#endif

#include "config.h"
#include "pttstruct.h"
#include "common.h"

unsigned string_hash(unsigned char *s);
void add_to_uhash(int n, userec_t *id);
void fill_uhash(void);
void load_uhash(void);

uhash_t *uhash;

int main() {
    setgid(BBSGID);
    setuid(BBSUID);
    chdir(BBSHOME);
    load_uhash();
    return 0;
}

void load_uhash(void) {
    int shmid;
    shmid = shmget(UHASH_KEY, sizeof(uhash_t), IPC_CREAT | 0600);
/* note we didn't use IPC_EXCL here.
   so if the loading fails,
   (like .PASSWD doesn't exist)
   we may try again later.
*/
    if (shmid < 0)
    {
    perror("shmget");
    exit(1);
    }

    uhash = (void *) shmat(shmid, NULL, 0);
    if (uhash == (void *) -1)
    {
    perror("shmat");
    exit(1);
    }

/* in case it's not assumed zero, this becomes a race... */
    uhash->loaded = 0;

    fill_uhash();

/* ok... */
    uhash->loaded = 1;
}

void fill_uhash(void)
{
    int fd, usernumber;
    usernumber = 0;

    for (fd = 0; fd < (1 << HASH_BITS); fd++)
    uhash->hash_head[fd] = -1;
    
    if ((fd = open(FN_PASSWD, O_RDONLY)) > 0)
    {
    struct stat stbuf;
    caddr_t fimage, mimage;

    fstat(fd, &stbuf);
    fimage = mmap(NULL, stbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
    if (fimage == (char *) -1)
    {
        perror("mmap");
        exit(1);
    }
    close(fd);
    fd = stbuf.st_size / sizeof(userec_t);
    if (fd > MAX_USERS)
        fd = MAX_USERS;
    
    for (mimage = fimage; usernumber < fd; mimage += sizeof(userec_t))
    {
        add_to_uhash(usernumber, mimage);
        usernumber++;
    }
    munmap(fimage, stbuf.st_size);
    }
    else
    {
    perror("open");
    exit(1);
    }
    uhash->number = usernumber;
    printf("total %d names loaded.\n", usernumber);
}
unsigned string_hash(unsigned char *s)
{
    unsigned int v = 0;
    while (*s)
    {
    v = (v << 8) | (v >> 24);
    v ^= toupper(*s++); /* note this is case insensitive */
    }
    return (v * 2654435769UL) >> (32 - HASH_BITS);
}

void add_to_uhash(int n, userec_t *user)
{
    int *p, h = string_hash(user->userid);
    strcpy(uhash->userid[n], user->userid);
    uhash->money[n] = user->money;
    p = &(uhash->hash_head[h]);

    while (*p != -1)
    p = &(uhash->next_in_hash[*p]);

    uhash->next_in_hash[*p = n] = -1;
}