aboutsummaryrefslogtreecommitdiff
path: root/command.c
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-03-14 11:05:35 +0100
committertomsmeding <tom.smeding@gmail.com>2017-03-14 11:05:35 +0100
commit54064158d84fc4006e651deb314cde156cc383e8 (patch)
treea534f160fe02b593143e03aaaf52f65513352c90 /command.c
Register working
Diffstat (limited to 'command.c')
-rw-r--r--command.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/command.c b/command.c
new file mode 100644
index 0000000..deaeabe
--- /dev/null
+++ b/command.c
@@ -0,0 +1,121 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/socket.h>
+#include "command.h"
+#include "db.h"
+
+
+static bool send_raw_text(int fd,const char *text,i64 len){
+ i64 cursor=0;
+ while(cursor<len){
+ i64 nwr=send(fd,text+cursor,len-cursor,0);
+ if(nwr<0){
+ if(errno==EINTR)continue;
+ if(errno==ECONNRESET||errno==EPIPE)return true;
+ die_perror("send");
+ }
+ cursor+=nwr;
+ }
+ return false;
+}
+
+static bool send_ok(int fd,const char *tag){
+ char *buf=NULL;
+ i64 len=asprintf(&buf,"%s ok\n",tag);
+ assert(buf);
+ bool closed=send_raw_text(fd,buf,len);
+ free(buf);
+ return closed;
+}
+
+static bool send_error(int fd,const char *tag,const char *msg){
+ char *buf=NULL;
+ i64 len=asprintf(&buf,"%s error %s\n",tag,msg);
+ assert(buf);
+ bool closed=send_raw_text(fd,buf,len);
+ free(buf);
+ return closed;
+}
+
+
+static bool cmd_register(int fd,const char *tag,const char **args){
+ i64 userid=db_find_user(args[0]);
+ if(userid!=-1){
+ send_error(fd,tag,"Username already exists");
+ return false;
+ }
+ db_create_user(args[0],args[1]);
+ return send_ok(fd,tag);
+}
+
+static bool cmd_login(int fd,const char *tag,const char **args){
+ (void)fd; (void)tag; (void)args;
+ return true;
+}
+
+
+struct cmd_info{
+ const char *cmdname;
+ int nargs;
+ bool longlast; // whether the last argument should span the rest of the input line
+ bool (*handler)(int fd,const char *tag,const char **args);
+};
+
+static const struct cmd_info commands[]={
+ {"register",2,false,cmd_register},
+ {"login",2,false,cmd_login},
+};
+#define NCOMMANDS (sizeof(commands)/sizeof(commands[0]))
+
+
+bool handle_input_line(int fd,char *line,size_t linelen){
+ char *sepp=memchr(line,' ',linelen);
+ if(sepp==NULL){
+ debug("No space in input line from connection %d",fd);
+ return true;
+ }
+ char *tag=line;
+ size_t taglen=sepp-tag;
+ *sepp='\0';
+ line+=taglen+1;
+ linelen-=taglen+1;
+
+ sepp=memchr(line,' ',linelen);
+ if(sepp==NULL)sepp=line+linelen;
+ size_t cmdlen=sepp-line;
+ size_t cmdi;
+ for(cmdi=0;cmdi<NCOMMANDS;cmdi++){
+ if(strncmp(line,commands[cmdi].cmdname,cmdlen)==0){
+ break;
+ }
+ }
+
+ int nargs=commands[cmdi].nargs;
+ char *args[nargs];
+ size_t cursor=cmdlen+1;
+
+ for(int i=0;i<nargs;i++){
+ if(cursor>=linelen){
+ debug("Connection %d sent too few parameters to command %s",fd,commands[cmdi].cmdname);
+ return true;
+ }
+ if(i==nargs-1&&commands[cmdi].longlast){
+ sepp=line+linelen;
+ } else {
+ sepp=memchr(line+cursor,' ',linelen-cursor);
+ if(sepp==NULL)sepp=line+linelen;
+ }
+ *sepp='\0';
+ args[i]=line+cursor;
+ cursor=sepp-line+1;
+ }
+ if(sepp-line<(i64)linelen){
+ debug("Connection %d sent too many parameters to command %s",fd,commands[cmdi].cmdname);
+ return true;
+ }
+
+ return commands[cmdi].handler(fd,tag,(const char**)args);
+}