aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile12
-rw-r--r--cforum.c68
-rw-r--r--front.c6
-rw-r--r--front.t11
-rwxr-xr-xmaketpl55
5 files changed, 152 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4bf3230
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+.SUFFIXES: .c .t .tc
+LDFLAGS += -lsqlite3
+
+cforum: cforum.c front.c front.tc
+ $(CC) $(CFLAGS) $(LDFLAGS) -o cforum cforum.c
+
+.t.tc: maketpl
+ <$< ./maketpl >$@
+
+db:
+ sqlite3 db "CREATE TABLE settings(key UNIQUE, value);"
+ sqlite3 db "INSERT INTO settings values('name', 'C Forum');" \ No newline at end of file
diff --git a/cforum.c b/cforum.c
new file mode 100644
index 0000000..a42a0b3
--- /dev/null
+++ b/cforum.c
@@ -0,0 +1,68 @@
+#include <sqlite3.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define warn(...) fprintf(stderr, __VA_ARGS__)
+#define die(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); }while(0)
+char *query(char *);
+struct site {
+ char *name;
+} site;
+
+#include "front.c"
+
+int
+main(int argc, char *argv[])
+{
+ char *qs;
+ sqlite3 *db;
+ sqlite3_stmt *res;
+
+ /* Retrieve site name from database. */
+ if(sqlite3_open("db", &db) != SQLITE_OK){
+ warn("%s\n", sqlite3_errmsg(db));
+ sqlite3_close(db);
+ return 1;
+ }
+
+ if(sqlite3_prepare(db,
+ "SELECT value FROM settings WHERE key = 'name'",
+ -1, &res, 0) != SQLITE_OK){
+ warn("%s\n", sqlite3_errmsg(db));
+ sqlite3_close(db);
+ return 1;
+ }
+
+ if(sqlite3_step(res) == SQLITE_ROW)
+ site.name = strdup(sqlite3_column_text(res, 0));
+
+ sqlite3_finalize(res);
+ sqlite3_close(db);
+
+ /* Handle request. */
+ qs = getenv("QUERY_STRING");
+ if(!qs || !*qs)
+ front();
+
+ return 0;
+}
+
+char *
+query(char *key)
+{
+ static char *qs;
+ char *w;
+ int n;
+
+ if(!qs) qs = getenv("QUERY_STRING");
+ if(!qs) die("no QUERY_STRING");
+
+ for(w = strtok(qs, "&"); w; w = strtok(NULL, "&")){
+ n = strcspn(w, "=");
+ if(strncmp(w, key, n) == 0)
+ return w + n + (w[n] == '=');
+ }
+
+ return NULL;
+} \ No newline at end of file
diff --git a/front.c b/front.c
new file mode 100644
index 0000000..6b8615c
--- /dev/null
+++ b/front.c
@@ -0,0 +1,6 @@
+void
+front()
+{
+ printf("Content-Type: text/html\n\n");
+ #include "front.tc"
+} \ No newline at end of file
diff --git a/front.t b/front.t
new file mode 100644
index 0000000..c2c416e
--- /dev/null
+++ b/front.t
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+<title><%= site.name %></title>
+</head>
+<body>
+<h1><%= site.name %></h1>
+<% printf("Hello world!"); %>
+</body>
+</html> \ No newline at end of file
diff --git a/maketpl b/maketpl
new file mode 100755
index 0000000..7908f3b
--- /dev/null
+++ b/maketpl
@@ -0,0 +1,55 @@
+#!/usr/bin/env perl
+
+# `maketpl' translates a template file (.t) to a C program (.tc)
+# that prints that template with the desired interpolations.
+
+use strict;
+use warnings;
+
+my $buf;
+
+while (<STDIN>) {
+ if (/(.*)\<%=(.+)%\>(.*)/) {
+ $buf .= $1;
+ flsh();
+ print qq(printf("%s", $2);\n);
+ if ($3) {
+ $buf .= "$3\n";
+ }
+ } elsif (/(.*)\<%/) {
+ my $code;
+ $buf .= $1;
+ flsh();
+ if (/\<%(.*)%\>(.*)/) {
+ $code = $1;
+ $buf .= $2;
+ $buf .= "\n";
+ } else {
+ /\<%(.*)/;
+ $code = $1;
+ while (<STDIN>) {
+ if (/(.*)%\>(.*)/) {
+ $code .= $1;
+ $buf .= $2;
+ $buf .= "\n";
+ last;
+ }
+ $code .= $_;
+ }
+ }
+ print $code;
+ } else {
+ $buf .= $_;
+ }
+}
+
+flsh();
+
+sub flsh {
+ return if not $buf;
+ $buf =~ s/\\/\\\\/g;
+ $buf =~ s/"/\\"/g;
+ $buf =~ s/\n/\\n/g;
+ print qq(printf("$buf");\n);
+ $buf = '';
+} \ No newline at end of file