--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "client.h"
+#include "proto.h"
+#include "repo.h"
+
+static int proc_request(struct client *c);
+static int proc_flist(struct client *c, char *data, int datasz);
+static int proc_push(struct client *c, char *data, int datasz);
+static int proc_pull(struct client *c, char *data, int datasz);
+
+const char *repo_path;
+
+int handle_client(struct client *c)
+{
+ char buf[512];
+ int sz, left;
+
+ while((sz = read(c->s, buf, sizeof buf)) > 0) {
+ left = sizeof c->buf - c->bsz;
+ if(sz > left) sz = left;
+ memcpy(c->buf + c->bsz, buf, sz);
+ c->bsz += sz;
+ }
+
+ if(proc_request(c) == -1) {
+ return -1;
+ }
+ return 0;
+}
+
+static int proc_request(struct client *c)
+{
+ char *endp = c->buf;
+ char *reqdata;
+ int reqdata_len;
+
+ while(endp < c->buf + c->bsz) {
+ if(*endp == '\n') break;
+ }
+ if(endp >= c->buf + c->bsz) {
+ return 0;
+ }
+ *endp = 0;
+
+ reqdata = endp + 1;
+ reqdata_len = c->bsz - (reqdata - c->buf);
+
+ c->bsz = 0;
+
+ if(strcmp(c->buf, "flist") == 0) {
+ return proc_flist(c, reqdata, reqdata_len);
+ } else if(strcmp(c->buf, "push") == 0) {
+ return proc_push(c, reqdata, reqdata_len);
+ } else if(strcmp(c->buf, "pull") == 0) {
+ return proc_pull(c, reqdata, reqdata_len);
+ } else if(strcmp(c->buf, "dos") == 0) {
+ c->flags |= CLIENT_DOS;
+ send_ok(c, 0);
+ return 0;
+ }
+
+ send_err(c);
+ return 0;
+}
+
+void send_string(struct client *c, const char *s)
+{
+ write(c->s, s, strlen(s));
+}
+
+void send_ok(struct client *c, int resp_sz)
+{
+ char buf[32];
+ sprintf(buf, "OK %d\n", resp_sz < 0 ? 0 : resp_sz);
+ send_string(c, buf);
+}
+
+void send_err(struct client *c)
+{
+ send_string(c, "ERR\n");
+}
+
+static struct flist *gen_flist(int contents)
+{
+ int i, count;
+ struct flist *flist;
+
+ if(!(flist = flist_create())) {
+ return 0;
+ }
+
+ if(repo_init(repo_path) == -1) {
+ return 0;
+ }
+ count = repo_num_files();
+
+ for(i=0; i<count; i++) {
+ flist_add(flist, repo_file(i)->path, contents);
+ }
+ repo_cleanup();
+
+ return flist;
+}
+
+static int proc_flist(struct client *c, char *data, int datasz)
+{
+ struct flist *flist;
+
+ if(!(flist = gen_flist(0))) {
+ send_err(c);
+ return -1;
+ }
+ flist_finalize(flist);
+
+ send_ok(c, flist->final_size);
+ write(c->s, flist->flist, flist->final_size);
+
+ flist_destroy(flist);
+ return 0;
+}
+
+static int proc_push(struct client *c, char *data, int datasz)
+{
+ send_err(c);
+ return 0;
+}
+
+static int proc_pull(struct client *c, char *data, int datasz)
+{
+ send_err(c);
+ return 0;
+}