From f41ec6d42942f994f762486a9ab525ed8c5506e5 Mon Sep 17 00:00:00 2001
From: Epoch Qwert <epoch@53flpnlls43fcguy.onion>
Date: Sun, 7 Sep 2014 02:37:46 -0500
Subject: took the hashtable stuff out of segfault and put it into a library.
 good idea? dunno.

---
 Makefile                    |   3 +-
 libhashtable/Makefile       |  14 ++++
 libhashtable/example.c      |  24 ++++++
 libhashtable/libhashtable.c | 115 ++++++++++++++++++++++++++
 libhashtable/libhashtable.h |  23 ++++++
 segfault.c                  | 193 ++++++++++----------------------------------
 6 files changed, 221 insertions(+), 151 deletions(-)
 create mode 100644 libhashtable/Makefile
 create mode 100644 libhashtable/example.c
 create mode 100644 libhashtable/libhashtable.c
 create mode 100644 libhashtable/libhashtable.h

diff --git a/Makefile b/Makefile
index 0806b5d..eedeed0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,9 @@
-LDFLAGS=-lirc -Llibirc
+LDFLAGS=-lirc -Llibirc -lhashtable -Llibhashtable
 CFLAGS=-pedantic -Wall
 
 all:
 	cd libirc && $(MAKE)
+	cd libhashtable && $(MAKE)
 	$(MAKE) segfault
 
 clean:
diff --git a/libhashtable/Makefile b/libhashtable/Makefile
new file mode 100644
index 0000000..7def401
--- /dev/null
+++ b/libhashtable/Makefile
@@ -0,0 +1,14 @@
+LDFLAGS=-lhashtable -Llibhashtable
+CFLAGS=-fpic -shared -pedantic -Wall
+TARGET=libhashtable.so
+
+all: $(TARGET)
+
+$(TARGET):
+	$(CC) $(CFLAGS) -o $(TARGET) libhashtable.c
+
+clean:
+	rm -f libhashtable.so
+
+install:
+	cp $(TARGET) /usr/local/lib/$(TARGET)
diff --git a/libhashtable/example.c b/libhashtable/example.c
new file mode 100644
index 0000000..614e440
--- /dev/null
+++ b/libhashtable/example.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include "libhashtable.h"
+
+extern char **environ;
+
+int main(int argc,char *argv[]) {
+ struct hashtable ht;
+ int i;
+ char *name;
+ char *value;
+ inittable(&ht);
+ for(i=0;environ[i];i++) {
+  name=strdup(environ[i]);
+  if((value=strchr(name,'=') )){
+   *value=0;
+   value++;
+  }
+  //printf("'%s' = '%s'\n",name,value);
+  ht_setkey(&ht,name,value);
+  free(name);
+ }
+ printf("PATH='%s'\n",ht_getvalue(&ht,"PATH"));
+ return 0;
+}
diff --git a/libhashtable/libhashtable.c b/libhashtable/libhashtable.c
new file mode 100644
index 0000000..c4ac2d3
--- /dev/null
+++ b/libhashtable/libhashtable.c
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "hashtable.h"
+
+/*
+struct entry {//linked list node.
+ char *original;
+ char *target;
+ struct entry *prev;// doubly linked list. why?
+ struct entry *next;
+};
+
+struct hitem {//dunno why I don't just have this as a linked list.
+ struct entry *ll;
+};
+
+struct hashtable {
+ int kl;//number of keys in the table
+ struct hitem **bucket;
+ int *keys;
+};
+*/
+
+unsigned short hash(char *v) {//maybe use a seeded rand()? :) Thanks FreeArtMan
+ unsigned short h=0;
+ h=((*v)<<8)+(v?*(v+1):0);
+ srand(h);
+ return rand();
+}
+
+void inittable(struct hashtable *ht,int tsize) {
+ int i;
+ ht->bucket=malloc(sizeof(char *)*tsize);
+ ht->kl=0;
+ ht->keys=malloc(sizeof(int *)*tsize);
+ if(!ht) {
+  fprintf(stderr,"malloc error 6 in hash table.\n");
+  return;
+ }
+ for(i=0;i<tsize;i++) {
+  ht->bucket[i]=0;
+ }
+}
+
+//this seems too complicated.
+int ht_setkey(struct hashtable *ht,char *key,char *value) {
+ unsigned short h=hash(key);
+ struct entry *tmp;
+ int i;
+ for(i=0;i<ht->kl;i++) {
+  if(ht->keys[i]==h) break;
+ }
+ ht->keys[i]=h;
+ ht->kl=(ht->kl)>i+1?ht->kl:i+1;
+ if(!ht->bucket[h]) { //empty bucket!
+  //add this to the list of used buckets so we can easily
+  //use that list later for stuff.
+  if(!(ht->bucket[h]=malloc(sizeof(struct hitem)))) return 1; 
+  ht->bucket[h]->ll=0;
+  //we now have a valid hashtable entry and a NULL ll in it.
+  //don't bother with the new ll entry yet...
+ }
+ if((tmp=ll_getentry(ht->bucket[h]->ll,key)) != NULL) {
+  //we found this alias in the ll. now to replace the value
+  free(tmp->target);
+  if(!(tmp->target=strdup(value))) return 2;
+  return 0;
+ }
+ if(ht->bucket[h]->ll == NULL) {
+  if(!(ht->bucket[h]->ll=malloc(sizeof(struct entry)))) return 3;
+  ht->bucket[h]->ll->next=0;
+  ht->bucket[h]->ll->prev=0;
+  if(!(ht->bucket[h]->ll->original=strdup(key))) return 4;
+  if(!(ht->bucket[h]->ll->target=strdup(value))) return 5;
+ } else {
+  //go to the end and add another entry to the ll.
+  for(tmp=ht->bucket[h]->ll;tmp->next;tmp=tmp->next);
+  if(!(tmp->next=malloc(sizeof(struct entry)))) return 6;
+  tmp->next->prev=tmp;
+  tmp=tmp->next;
+  if(!(tmp->original=strdup(key))) return 7;
+  if(!(tmp->target=strdup(value))) return 8;
+  tmp->next=0;
+ }
+ return 0;
+}
+
+struct entry *ll_getentry(struct entry *start,char *msg) {
+ struct entry *m;
+ if(!msg) return NULL;
+ if(!start) return NULL;
+ for(m=start;m;m=m->next) {
+  if(!strncmp(msg,m->original,strlen(m->original)) && (msg[strlen(m->original)]==' ' || msg[strlen(m->original)] == 0)) {//this allows !c to get called when using !c2 if !c2 is defined after !c. >_>
+   return m;
+  }
+ }
+ return NULL;
+}
+
+struct entry *ht_getentry(struct hashtable *ht,char *key) {
+ unsigned short h=hash(key);
+ if(!ht->bucket[h]) return NULL;
+ return ht->bucket[h]->ll;
+}
+
+struct entry *ht_getnode(struct hashtable *ht,char *msg) {
+ return ll_getentry(ht_getentry(ht,msg),msg);
+}
+
+//you'll probably want to use me.
+char *ht_getvalue(struct hashtable *ht,char *msg) {
+ struct entry *tmp=ll_getentry(ht_getentry(ht,msg),msg);
+ return tmp?tmp->target:0;
+}
diff --git a/libhashtable/libhashtable.h b/libhashtable/libhashtable.h
new file mode 100644
index 0000000..7899124
--- /dev/null
+++ b/libhashtable/libhashtable.h
@@ -0,0 +1,23 @@
+struct entry {//linked list node.
+ char *original;
+ char *target;
+ struct entry *prev;// doubly linked list. why?
+ struct entry *next;
+};
+
+struct hitem {//dunno why I don't just have this as a linked list.
+ struct entry *ll;
+};
+
+struct hashtable {
+ int kl;//number of keys in the table
+ struct hitem **bucket;
+ int *keys;
+};
+unsigned short hash(char *v);//maybe use a seeded rand()? :) Thanks FreeArtMan
+void inittable(struct hashtable *ht);
+int ht_setkey(struct hashtable *ht,char *key,char *value);
+struct entry *ll_getentry(struct entry *start,char *msg);
+struct entry *ht_getentry(struct hashtable *ht,char *key);
+struct entry *ht_getnode(struct hashtable *ht,char *msg);
+char *ht_getvalue(struct hashtable *ht,char *msg);
diff --git a/segfault.c b/segfault.c
index 5f1499b..7425a04 100644
--- a/segfault.c
+++ b/segfault.c
@@ -8,9 +8,12 @@
 #include <fcntl.h>
 #include <time.h>
 #include <pwd.h>
+
 #include "libirc/irc.h" //epoch's libirc. should be included with segfault.
+#include "libhashtable/hashtable.h" //epoch's also.
 
 //might want to change some of these.
+#define TSIZE			65535
 #define SERVER			"127.0.0.1"
 #define PORT			"6667"
 #define NICK			"SegFault" //override with argv[0]
@@ -21,7 +24,6 @@
 #define LOG			"./files/log"
 #define MAXTAILS		400 //just to have it more than the system default.
 #define BS 502
-#define TSIZE 65536             //size of hashtable. 65k isn't bad, right?
 // !c uses 56 for its tail.
 // 56 == 32 + 16 + 8 == 0x38 == 0x20+0x10+0x8 == SPAM | BEGIN | MSG
 #define TAILO_RAW    (0x1) // r output gets sent directly to server
@@ -63,6 +65,8 @@ timer_t timer;
 int lines_sent;
 unsigned long oldtime;
 
+struct hashtable alias;
+
 struct user {
  char *nick;
  char *name;
@@ -80,13 +84,6 @@ struct tail {
  int lines;
 } tailf[MAXTAILS];
 
-struct alias {
- char *original;
- char *target;
- struct alias *prev;// doubly linked list.
- struct alias *next;
-};
-
 char *shitlist[] = { 0 };
 
 void message_handler(int fd,char *from,struct user *user,char *msg,int redones);
@@ -417,108 +414,20 @@ void debug_time(int fd,char *from,char *msg) {
  }
 }
 
-struct alias *leetgetalias(struct alias *start,char *msg) {
- struct alias *m;
- if(!msg) return NULL;
- if(!start) return NULL;
- for(m=start;m;m=m->next) {
-  if(!strncmp(msg,m->original,strlen(m->original)) && (msg[strlen(m->original)]==' ' || msg[strlen(m->original)] == 0)) {//this allows !c to get called when using !c2 if !c2 is defined after !c. >_>
-   return m;
-  }
- }
- return NULL;
-}
-
-unsigned short hash(char *v) {//maybe use a seeded rand()? :) Thanks FreeArtMan
- unsigned short h=0;
- h=((*v)<<8)+(v?*(v+1):0);
- srand(h);
- return rand();
-}
-
-struct hitem {//with a stick
- struct alias *ll;
-};
-
-struct hitem **hashtable;
-int htkeys[TSIZE];
-int htkl;
-
-void inittable() {
- int i;
- hashtable=malloc(sizeof(char *)*TSIZE);
- if(!hashtable) {
-  fprintf(stderr,"malloc error 6 in hash table.\n");
-  return;
- }
- for(i=0;i<TSIZE;i++) {
-  hashtable[i]=0;
- }
-}
-
-struct alias *getkey_h(char *key) {
- unsigned short h=hash(key);
- if(!hashtable[h]) return NULL;
- return hashtable[h]->ll;
-}
-
-//this seems too complicated.
-int setkey_h(char *key,char *value) {
- unsigned short h=hash(key);
- struct alias *tmp;
- int i;
- for(i=0;i<htkl;i++) {
-  if(htkeys[i]==h) break;
- }
- htkeys[i]=h;
- htkl=htkl>i+1?htkl:i+1;
- if(!hashtable[h]) { //empty bucket!
-  //add this to the list of used buckets so we can easily
-  //use that list later for stuff.
-  if(!(hashtable[h]=malloc(sizeof(struct hitem)))) return 1; 
-  hashtable[h]->ll=0;
-  //we now have a valid hashtable entry and a NULL ll in it.
-  //don't bother with the new ll entry yet...
- }
- if((tmp=leetgetalias(hashtable[h]->ll,key)) != NULL) {
-  //we found this alias in the ll. now to replace the value
-  free(tmp->target);
-  if(!(tmp->target=strdup(value))) return 2;
-  return 0;
- }
- if(hashtable[h]->ll == NULL) {
-  if(!(hashtable[h]->ll=malloc(sizeof(struct alias)))) return 3;
-  hashtable[h]->ll->next=0;
-  hashtable[h]->ll->prev=0;
-  if(!(hashtable[h]->ll->original=strdup(key))) return 4;
-  if(!(hashtable[h]->ll->target=strdup(value))) return 5;
- } else {
-  //go to the end and add another entry to the ll.
-  for(tmp=hashtable[h]->ll;tmp->next;tmp=tmp->next);
-  if(!(tmp->next=malloc(sizeof(struct alias)))) return 6;
-  tmp->next->prev=tmp;
-  tmp=tmp->next;
-  if(!(tmp->original=strdup(key))) return 7;
-  if(!(tmp->target=strdup(value))) return 8;
-  tmp->next=0;
- }
- return 0;
-}
-
 void c_aliases_h(int fd,char *from,char *line) {
  char tmp[512];
- struct alias *m;
+ struct entry *m;
  int i,j=0,k=0;
  if(!line){
   privmsg(fd,from,"usage: !aliases [search-term]");
   return;
  }
- for(i=0;i<htkl;i++) {
-  //snprintf(tmp,sizeof(tmp)-1,"aliases in bucket: %d",htkeys[i]);
+ for(i=0;i<alias.kl;i++) {
+  //snprintf(tmp,sizeof(tmp)-1,"aliases in bucket: %d",alias->keys[i]);
   //privmsg(fd,from,tmp);
-  for(m=hashtable[htkeys[i]]->ll;m;m=m->next) {
+  for(m=alias.bucket[alias.keys[i]]->ll;m;m=m->next) {
    if(strcasestr(m->target,line) || strcasestr(m->original,line)) {
-    snprintf(tmp,sizeof(tmp)-1,"%s -> %s",m->original,m->target);
+    snprintf(tmp,sizeof(tmp)-1," %s -> %s",m->original,m->target);
     privmsg(fd,from,tmp);
     j++;
    }
@@ -528,49 +437,17 @@ void c_aliases_h(int fd,char *from,char *line) {
  snprintf(tmp,sizeof(tmp)-1,"found %d of %d aliases",j,k);
  privmsg(fd,from,tmp);
 }
-
-//CONVERT //this is the last one that needs to be converted to
-// be used with the hashtable
 /*
-void c_rmalias_h(int fd,char *from,char *line) {
-
-}
-
-void c_leetrmalias(int fd,char *from,char *line) {
- struct alias *m;
- for(m=a_start;m;m=m->next) {
-  if(!strcmp(line,m->original)) {
-   if(m->next == 0) {
-    a_end=m->prev;
-   }
-   if(m->prev == 0) {
-    a_start=m->next;
-    free(m->target);
-    free(m->original);
-    free(m);
-   }
-   else {
-    m->prev->next=m->next;
-   }
-   privmsg(fd,from,"alias deleted");
-   return;
-  }
- }
- privmsg(fd,from,"alias not found");
- return;
-}
-*/
-
-struct alias *getalias_h(char *msg) {
+struct entry *getalias_h(char *msg) {
  return leetgetalias(getkey_h(msg),msg);
 }
-
+*/
 void c_alias_h(int fd,char *from,char *line) {
  char tmps[512];
  char *derp=strchr(line,' ');
- struct alias *tmp;
+ struct entry *tmp;
  if(!derp) {
-  if((tmp=getalias_h(line)) != NULL) {
+  if((tmp=ht_getentry(&alias,line)) != NULL) {
    privmsg(fd,from,tmp->target);
   } else {
    snprintf(tmps,sizeof(tmps),"'%s' not an alias.",line);
@@ -580,7 +457,7 @@ void c_alias_h(int fd,char *from,char *line) {
  }
  *derp=0;
  derp++;
- setkey_h(line,derp);
+ ht_setkey(&alias,line,derp);
 }
 
 //hash table version
@@ -858,7 +735,10 @@ void c_resetout(int fd,char *from) {
  privmsg(fd,from,"output reset");
 }
 
-/* maybe... that message hander is ugly.
+/* maybe... that message handler is ugly.
+//an array of built-ins? linked list? hash-table?
+//working on genericizing the hash-table code.
+//so probably ht for builtins.
 struct builtin {
  char *cmd;
  void (*func)();
@@ -870,8 +750,7 @@ struct builtin[] = {
 */
 
 void message_handler(int fd,char *from,struct user *user,char *msg,int redones) {
- printf("message handler!\n");
- struct alias *m;
+ struct entry *m;
  char *tmp2;
  char tmp[512];
  int len;
@@ -915,6 +794,18 @@ void message_handler(int fd,char *from,struct user *user,char *msg,int redones)
  //... meh. it'd just be a LITTLE bit shorter.
 
  // this still seems horrible though. all those constants in there that are just strlen()s...
+#ifdef USE_BUILTIN_HT
+ char *command;
+ char *args;
+ command=strcpy(msg);
+ if((args=strchr(' ',msg))) {
+  *args=0;
+  args++;
+ }
+ if(builtin[hash(command)]) {
+  builtin[hash(command)]->value(args);
+ }
+#else
  if(!strncmp(msg,"!leetsetout ",12)) {
   c_leetsetout(fd,from,msg+12);
  }
@@ -995,10 +886,10 @@ void message_handler(int fd,char *from,struct user *user,char *msg,int redones)
  else if(!strncmp(msg,"!aliases",8) && (!msg[8] || msg[8] == ' ')) {
   c_aliases_h(fd,from,*(msg+8)?msg+9:0);
  }
-
+#endif
  else if(redones < 5) {
   debug_time(fd,from,"checking aliases...");
-  if((m=getalias_h(msg)) != NULL) {
+  if((m=ht_getentry(&alias,msg)) != NULL) {
    sz=(strlen(msg)-strlen(m->original)+strlen(m->target)+1);
    redo=format_magic(fd,from,user,m->target,*(msg+strlen(m->original)+1)=='\n'?"":(msg+strlen(m->original)+1));
    message_handler(fd,from,user,redo,redones+1);
@@ -1017,12 +908,12 @@ void message_handler(int fd,char *from,struct user *user,char *msg,int redones)
 }
 
 void line_handler(int fd,char *line) {//this should be built into the libary?
- printf("line: %s\n",line);
  char *s=line,*t=0,*u=0;
  struct user *user=malloc(sizeof(struct user));
  user->nick=0;
  user->name=0;
  user->host=0;
+ printf("line: %s\n",line);
  if(strchr(line,'\r')) *strchr(line,'\r')=0;
  if(strchr(line,'\n')) *strchr(line,'\n')=0;
  //:nick!name@host MERP DERP :message
@@ -1085,15 +976,18 @@ void line_handler(int fd,char *line) {//this should be built into the libary?
   }
  }
  if(s && t && u) {
-  if(!strcmp(s,"PRIVMSG") && strcmp(user->nick,myuser->nick))
-   if(strcmp(user->nick,myuser->nick))
+  if(!strcmp(s,"PRIVMSG") && strcmp(user->nick,myuser->nick)) {
+   if(strcmp(user->nick,myuser->nick)) {
     message_handler(fd,*t=='#'?t:user->nick,user,++u,0);
-   else
+   }
+   else {
     if(debug) privmsg(fd,*t=='#'?t:user->nick,"This server has an echo");
+   }
+  }
  }
  if(s && user->nick && t) {
   if(!strcmp(s,"JOIN")) {
-   irc_mode(fd,t+1,"+v",user->nick);//why t+1? it starts with :?
+   irc_mode(fd,t+1,"+o",user->nick);//why t+1? it starts with :?
   }
   if(!strcmp(s,"MODE") && mode_magic) {
    if(u) {
@@ -1129,9 +1023,8 @@ int main(int argc,char *argv[]) {
  recording=0;
  recording_raw=0;
  start_time=time(0);
- htkl=0;
  redo=0;
- inittable();
+ inittable(&alias,TSIZE);
  myuser=malloc(sizeof(struct user));
  myuser->nick=strdup(argc>1?argv[1]:NICK);
  myuser->name="I_dunno";
-- 
cgit v1.2.3