--- /dev/null
+/* Gateway kernel
+ * Europagate, 1995
+ *
+ * $Log: gip.c,v $
+ * Revision 1.1 1995/03/27 08:24:58 adam
+ * New module gip: Gateway IPc module.
+ * New module gw-db: Gateway hash-db module (user information table).
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <gip.h>
+
+GIP gip_initialize (const char *name)
+{
+ GIP gip = malloc (sizeof(*gip));
+
+ if (!gip)
+ return NULL;
+ if (!(gip->name = malloc (strlen(name)+1)))
+ {
+ free (gip);
+ return NULL;
+ }
+ strcpy (gip->name, name);
+ gip->ret = mknod (gip->name, S_IFIFO|0666, 0);
+ gip->errno = errno;
+ return gip;
+}
+
+int gip_destroy (GIP gip)
+{
+ assert (gip);
+
+ free (gip->name);
+ free (gip);
+ return 0;
+}
+
+int gip_infileno (GIP gip)
+{
+ return gip->rfd;
+}
+
+int gip_errno (GIP gip)
+{
+ return gip->errno;
+}
+
+int gip_read (GIP gip, char *buf, size_t count)
+{
+ int r, no = 0;
+ while (no < count)
+ {
+ r = read (gip->rfd, buf+no, count-no);
+ if (r == -1)
+ {
+ gip->errno = errno;
+ return -1;
+ }
+ no += r;
+ }
+ return 0;
+}
+
+int gip_write (GIP gip, const char *buf, size_t count)
+{
+ int r, no = 0;
+ while (no < count)
+ {
+ r = write (gip->wfd, buf+no, count-no);
+ if (r == -1)
+ {
+ gip->errno = errno;
+ return -1;
+ }
+ no += r;
+ }
+ return 0;
+}
+
+int gip_wline (GIP gip, const char *buf)
+{
+ return gip_write (gip, buf, strlen(buf));
+}
+
--- /dev/null
+/* Gateway utility
+ * Europagate, 1995
+ *
+ * $Log: gw-db.c,v $
+ * Revision 1.1 1995/03/27 08:25:01 adam
+ * New module gip: Gateway IPc module.
+ * New module gw-db: Gateway hash-db module (user information table).
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <gw-db.h>
+
+#define FILE_HEAD_LEN 128
+#define DB_HASH 1997
+
+struct gw_db {
+ struct file_head {
+ char magic[8];
+ int no_of_entries;
+ int sequence_no;
+ } head;
+ int *hash_array;
+ int fd;
+ int dirty;
+};
+
+struct db_bucket {
+ int name_length;
+ int info_length;
+ int next;
+ int prev;
+};
+
+static int write_head (GW_DB db)
+{
+ char file_head_buf[FILE_HEAD_LEN];
+ int r;
+
+ if (lseek (db->fd, 0L, SEEK_SET) == -1)
+ return -1;
+ memcpy (file_head_buf, &db->head, sizeof(db->head));
+ r = write (db->fd, file_head_buf, FILE_HEAD_LEN);
+ if (r == -1)
+ return -1;
+ r = write (db->fd, db->hash_array, DB_HASH * sizeof(*db->hash_array));
+ if (r == -1)
+ return -1;
+ return 0;
+}
+
+static unsigned hash (const char *name)
+{
+ unsigned l = 0;
+
+ while (*name)
+ l = l*65599 + *name++;
+ return l % DB_HASH;
+}
+
+static void lock_file (int fd, int type)
+{
+ struct flock area;
+ area.l_type = type;
+ area.l_whence = SEEK_SET;
+ area.l_start = 0L;
+ area.l_len = 0L;
+ fcntl (fd, F_SETLKW, &area);
+}
+
+int gw_db_lookup (GW_DB db, const char *name, int name_length,
+ void **buf, size_t *count)
+{
+ struct db_bucket bucket;
+ unsigned l = hash (name);
+ char *dbuf = NULL;
+ int dsize = 0;
+ int pos;
+ int r;
+
+ for (pos = db->hash_array[l]; pos; pos = bucket.next)
+ {
+ int blen;
+
+ if (lseek (db->fd, pos, SEEK_SET) == -1)
+ {
+ free (dbuf);
+ return -1;
+ }
+ r = read (db->fd, &bucket, sizeof(bucket));
+ if (r == -1)
+ {
+ free (dbuf);
+ return -1;
+ }
+ if (r != sizeof(bucket))
+ {
+ free (dbuf);
+ return -2;
+ }
+ if (bucket.name_length <= 0 || bucket.info_length <= 0 ||
+ bucket.name_length >= 16384 || bucket.info_length >= 262144)
+ {
+ free (dbuf);
+ return -3;
+ }
+ if (bucket.name_length != name_length)
+ continue;
+ blen = bucket.name_length + bucket.info_length;
+ if (blen >= dsize)
+ {
+ dsize = blen + 1024;
+ free (dbuf);
+ if (!(dbuf = malloc (dsize)))
+ return -1;
+ }
+ r = read (db->fd, dbuf, blen);
+ if (r == -1)
+ {
+ free (dbuf);
+ return -1;
+ }
+ else if (r < blen)
+ {
+ free (dbuf);
+ return -2;
+ }
+ if (memcmp (name, dbuf, name_length))
+ continue;
+
+ *count = bucket.info_length;
+ *buf = malloc (*count);
+ if (!*buf)
+ {
+ free (dbuf);
+ return -1;
+ }
+ memcpy (*buf, dbuf + name_length, *count);
+ free (dbuf);
+ return 1;
+ }
+ free (dbuf);
+ return 0;
+}
+
+int gw_db_insert (GW_DB db, const char *name, int name_length,
+ const void *buf, size_t count)
+{
+ struct db_bucket n_bucket;
+ struct db_bucket bucket;
+ off_t n_pos, r_pos;
+ unsigned l = hash (name);
+ int pos = db->hash_array[l];
+ int r;
+
+ db->dirty = 1;
+ (db->head.no_of_entries)++;
+ (db->head.sequence_no)++;
+ n_bucket.name_length = name_length;
+ n_bucket.info_length = count;
+ n_pos = lseek (db->fd, 0, SEEK_END);
+ if (n_pos == -1)
+ return -1;
+ n_bucket.next = pos;
+ db->hash_array[l] = n_pos;
+ n_bucket.prev = 0;
+
+ r = write (db->fd, &n_bucket, sizeof(n_bucket));
+ if (r == -1)
+ return -1;
+ else if (r < sizeof(n_bucket))
+ return -2;
+
+ r = write (db->fd, name, name_length);
+ if (r == -1)
+ return -1;
+ else if (r < name_length)
+ return -2;
+
+ r = write (db->fd, buf, count);
+ if (r == -1)
+ return -1;
+ else if (r < count)
+ return -2;
+
+ r_pos = lseek (db->fd, pos, SEEK_SET);
+ if (r_pos == -1)
+ return -1;
+ r = read (db->fd, &bucket, sizeof(bucket));
+ if (r == -1)
+ return -1;
+ else if (r < sizeof(bucket))
+ return -2;
+ bucket.prev = n_pos;
+
+ r_pos = lseek (db->fd, pos, SEEK_SET);
+ if (r_pos == -1)
+ return -1;
+ r = write (db->fd, &bucket, sizeof(bucket));
+ if (r == -1)
+ return -1;
+ else if (r < sizeof(bucket))
+ return -2;
+ return 0;
+}
+
+static GW_DB gw_db_free (GW_DB db)
+{
+ free (db->hash_array);
+ free (db);
+ return NULL;
+}
+
+GW_DB gw_db_open (const char *fname, int write_flag)
+{
+ char file_head_buf[FILE_HEAD_LEN];
+ GW_DB db;
+ int r;
+
+ if (!(db = malloc (sizeof(*db))))
+ return NULL;
+ db->dirty = 0;
+ if (!(db->hash_array = malloc (DB_HASH * sizeof(*db->hash_array))))
+ return gw_db_free (db);
+ if (write_flag)
+ db->fd = open (fname, O_RDWR|O_CREAT, 0666);
+ else
+ db->fd = open (fname, O_RDONLY);
+ if (db->fd == -1)
+ return gw_db_free (db);
+ lock_file (db->fd, write_flag ? F_WRLCK : F_RDLCK);
+ r = read (db->fd, file_head_buf, FILE_HEAD_LEN);
+ if (r == -1)
+ return gw_db_free (db);
+ if (r < FILE_HEAD_LEN)
+ {
+ int i;
+
+ if (!write_flag)
+ return gw_db_free (db);
+ db->head.no_of_entries = 0;
+ db->head.sequence_no = 1;
+ for (i=0; i<DB_HASH; i++)
+ db->hash_array[i] = 0;
+ if (write_head (db))
+ return gw_db_free (db);
+ }
+ else
+ {
+ memcpy (&db->head, file_head_buf, sizeof(db->head));
+ r = read (db->fd, db->hash_array, sizeof(*db->hash_array)*DB_HASH);
+ if (r < sizeof(*db->hash_array)*DB_HASH)
+ return gw_db_free (db);
+ }
+ return db;
+}
+
+
+int gw_db_close (GW_DB db)
+{
+ int r = 0;
+
+ if (db->dirty)
+ r = write_head (db);
+ lock_file (db->fd, F_UNLCK);
+ if (close (db->fd) == -1)
+ {
+ gw_db_free (db);
+ return -1;
+ }
+ gw_db_free (db);
+ return r;
+}
+
+int gw_db_no_ent (GW_DB db)
+{
+ return db->head.no_of_entries;
+}
+
+int gw_db_seq_no (GW_DB db)
+{
+ return db->head.sequence_no;
+}
+
--- /dev/null
+/* Gateway db utility test
+ * Europagate, 1995
+ *
+ * $Log: gwdbtest.c,v $
+ * Revision 1.1 1995/03/27 08:25:02 adam
+ * New module gip: Gateway IPc module.
+ * New module gw-db: Gateway hash-db module (user information table).
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include <gw-db.h>
+
+int main (int argc, char **argv)
+{
+ char word[1024];
+ GW_DB gwdb;
+ int no;
+ void *buf;
+ size_t count;
+ int r;
+ int no_insert = 0;
+
+ gwdb = gw_db_open ("db.test", 1);
+ for (no = 0; scanf ("%s", word) == 1; no++)
+ {
+ r = gw_db_lookup (gwdb, word, strlen(word), & buf, &count);
+ if (r== 0)
+ {
+ char info[25];
+ sprintf (info, "%d", no);
+ if (gw_db_insert (gwdb, word, strlen(word), info, strlen (info)))
+ {
+ printf ("gw_db_insert of %s failed\n", word);
+ exit (1);
+ }
+ no_insert++;
+ }
+ else if (r == 1)
+ {
+ free (buf);
+ }
+ else
+ {
+ printf ("gw_db_lookup of %s failed\n", word);
+ exit (1);
+ }
+ }
+ gw_db_close (gwdb);
+ printf ("Lookup: %d. Insert: %d\n", no, no_insert);
+ exit (0);
+}