changeset 13:76cee581f48b

story: work in progress
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Wed, 04 Feb 2009 01:14:15 -0500
parents b5ea996aa617
children 06b2d0a67c4d
files Makefile html.c html.h post.c post.h sar.c sar.h story.c xattr.c xattr.h
diffstat 10 files changed, 454 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Wed Feb 04 01:14:15 2009 -0500
@@ -0,0 +1,9 @@
+CC=gcc
+CFLAGS=-Wall -g -O2
+
+FILES=sar.c post.c xattr.c html.c
+
+all: story
+
+story: story.c $(FILES)
+	$(CC) $(CFLAGS) -o $@ story.c $(FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/html.c	Wed Feb 04 01:14:15 2009 -0500
@@ -0,0 +1,75 @@
+#include <stdio.h>
+
+#include "sar.h"
+#include "html.h"
+
+/************************************************************************/
+/*                                POST                                  */
+/************************************************************************/
+void html_story(struct post *post)
+{
+	cat(post, "templates/story-top.html", repltab_html);
+
+#if 0
+	for_each_category(post)
+		cat(stdout, "templates/story-cat-item.html", repltab_html);
+#endif
+
+	cat(post, "templates/story-middle.html", repltab_html);
+
+	cat_post(post);
+
+	cat(post, "templates/story-bottom.html", NULL);
+}
+
+/************************************************************************/
+/*                           POST COMMENTS                              */
+/************************************************************************/
+void html_comments(struct post *post)
+{
+	cat(post, "templates/story-comment-head.html", repltab_html);
+
+#if 0
+	for_each_comment(post) {
+		cat(post, "templates/story-comment-item-head.html", repltab_html);
+		cat_post_comment(post, commentid);
+		cat(post, "templates/story-comment-item-tail.html", repltab_html);
+	}
+#endif
+
+	cat(post, "templates/story-comment-tail.html", repltab_html);
+}
+
+/************************************************************************/
+/*                                 SIDEBAR                              */
+/************************************************************************/
+void html_sidebar(struct post *post)
+{
+	cat(post, "templates/sidebar-top.html", repltab_html);
+#if 0
+	for_each_category()
+		cat(post, "templates/sidebar-cat-item.html", repltab_html);
+#endif
+	cat(post, "templates/sidebar-middle.html", repltab_html);
+#if 0
+	for_each_month()
+		cat(post, "templates/sidebar-archive-item.html", repltab_html);
+#endif
+	cat(post, "templates/sidebar-bottom.html", repltab_html);
+}
+
+/************************************************************************/
+/*                             PAGE HEADER                              */
+/************************************************************************/
+void html_header(struct post *post)
+{
+	cat(post, "templates/header.html", repltab_html);
+}
+
+/************************************************************************/
+/*                             PAGE FOOTER                              */
+/************************************************************************/
+void html_footer(struct post *post)
+{
+	cat(post, "templates/footer.html", repltab_html);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/html.h	Wed Feb 04 01:14:15 2009 -0500
@@ -0,0 +1,12 @@
+#ifndef __HTML_H
+#define __HTML_H
+
+#include "post.h"
+
+extern void html_story(struct post *post);
+extern void html_comments(struct post *post);
+extern void html_sidebar(struct post *post);
+extern void html_header(struct post *post);
+extern void html_footer(struct post *post);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/post.c	Wed Feb 04 01:14:15 2009 -0500
@@ -0,0 +1,119 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "post.h"
+#include "xattr.h"
+#include "sar.h"
+
+void cat(struct post *post, char *tmpl, struct repltab_entry *repltab)
+{
+	struct stat statbuf;
+	char *ibuf;
+	int ret;
+	int fd;
+
+	fd = open(tmpl, O_RDONLY);
+	if (fd == -1) {
+		fprintf(post->out, "template open error\n");
+		return;
+	}
+
+	ret = fstat(fd, &statbuf);
+	if (ret == -1) {
+		fprintf(post->out, "fstat failed\n");
+		goto out_close;
+	}
+
+	ibuf = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
+	if (ibuf == MAP_FAILED) {
+		fprintf(post->out, "mmap failed\n");
+		goto out_close;
+	}
+
+	sar(post, ibuf, statbuf.st_size, repltab);
+
+	munmap(ibuf, statbuf.st_size);
+
+out_close:
+	close(fd);
+}
+
+void cat_post(struct post *post)
+{
+	char path[FILENAME_MAX];
+	struct stat statbuf;
+	char *ibuf;
+	int ret;
+	int fd;
+
+	snprintf(path, FILENAME_MAX, "data/posts/%d/post.txt", post->id);
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1) {
+		fprintf(post->out, "post.txt open error\n");
+		return;
+	}
+
+	ret = fstat(fd, &statbuf);
+	if (ret == -1) {
+		fprintf(post->out, "fstat failed\n");
+		goto out_close;
+	}
+
+	ibuf = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
+	if (ibuf == MAP_FAILED) {
+		fprintf(post->out, "mmap failed\n");
+		goto out_close;
+	}
+
+	/* FIXME: do <p> insertion, etc. */
+	fwrite(ibuf, 1, statbuf.st_size, post->out);
+
+	munmap(ibuf, statbuf.st_size);
+
+out_close:
+	close(fd);
+}
+
+int load_post(int postid, struct post *post)
+{
+	char path[FILENAME_MAX];
+
+	snprintf(path, FILENAME_MAX, "data/posts/%d", postid);
+
+	post->id = postid;
+	post->title = safe_getxattr(path, XATTR_TITLE);
+	post->cats  = safe_getxattr(path, XATTR_CATS);
+	post->time  = safe_getxattr(path, XATTR_TIME);
+
+	if (post->title && post->time)
+		return 0;
+
+	destroy_post(post);
+	return ENOMEM;
+}
+
+void destroy_post(struct post *post)
+{
+	free(post->title);
+	free(post->cats);
+	free(post->time);
+}
+
+void dump_post(struct post *post)
+{
+	if (!post)
+		fprintf(stdout, "p=NULL\n");
+	else
+		fprintf(post->out, "p=%p { %d, '%s', '%s', '%s' }\n\n",
+			post, post->id, post->title, post->cats,
+			post->time);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/post.h	Wed Feb 04 01:14:15 2009 -0500
@@ -0,0 +1,25 @@
+#ifndef __POST_H
+#define __POST_H
+
+struct post {
+	FILE *out;
+	int id;
+	char *title;
+	char *cats;
+	char *time;
+};
+
+#define XATTR_TITLE	"user.post_title"
+#define XATTR_CATS	"user.post_cats"
+#define XATTR_TIME	"user.post_time"
+
+extern int load_post(int postid, struct post *post);
+extern void dump_post(struct post *post);
+extern void destroy_post(struct post *post);
+
+struct repltab_entry;
+
+extern void cat_post(struct post *post);
+extern void cat(struct post *post, char *tmpl, struct repltab_entry *repltab);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sar.c	Wed Feb 04 01:14:15 2009 -0500
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "post.h"
+#include "sar.h"
+
+static void echo_postid(struct post *post)
+{
+	fprintf(post->out, "%d", post->id);
+}
+
+static void echo_title(struct post *post)
+{
+	fprintf(post->out, "%s", post->title);
+}
+
+static void echo_posttime(struct post *post)
+{
+	fprintf(post->out, "||posttime||");
+}
+
+static void echo_postdate(struct post *post)
+{
+	fprintf(post->out, "||postdate||");
+}
+
+static struct repltab_entry __repltab_html[] = {
+	{"POSTID",	echo_postid},
+	{"POSTDATE",	echo_postdate},
+	{"POSTTIME",	echo_posttime},
+	{"TITLE",	echo_title},
+	{"",		NULL},
+};
+
+struct repltab_entry *repltab_html = __repltab_html;
+
+static int invoke_repl(struct post *post, char *cmd,
+		       struct repltab_entry *repltab)
+{
+	int i;
+
+	if (!repltab)
+		return 1;
+
+	for(i=0; repltab[i].f; i++) {
+		if (strcmp(cmd, repltab[i].what))
+			continue;
+
+		repltab[i].f(post);
+		return 0;
+	}
+
+	return 1;
+}
+
+#define SAR_NORMAL	0
+#define SAR_WAIT1	1
+#define SAR_WAIT2	2
+#define SAR_SPECIAL	3
+#define SAR_ERROR	4
+
+#define COPYCHAR(ob, oi, c)	do { \
+					ob[oi] = c; \
+					oi++; \
+				} while(0)
+
+void sar(struct post *post, char *ibuf, int size,
+	 struct repltab_entry *repltab)
+{
+	char obuf[size];
+	char cmd[16];
+	int iidx, oidx, cidx;
+	int state = SAR_NORMAL;
+	char tmp;
+
+	for(iidx = oidx = cidx = 0; (iidx < size) && (state != SAR_ERROR); iidx++) {
+		tmp = ibuf[iidx];
+#if 0
+		fprintf(post->out, "\n| cur '%c', state %d| ", tmp, state);
+#endif
+
+		switch(state) {
+			case SAR_NORMAL:
+				if (tmp == '@')
+					state = SAR_WAIT1;
+				else
+					COPYCHAR(obuf, oidx, tmp);
+				break;
+
+			case SAR_WAIT1:
+				if (tmp == '@') {
+					state = SAR_SPECIAL;
+					COPYCHAR(obuf, oidx, '\0');
+					fprintf(post->out, obuf);
+					oidx = 0;
+				} else {
+					state = SAR_NORMAL;
+					COPYCHAR(obuf, oidx, '@');
+					COPYCHAR(obuf, oidx, tmp);
+				}
+				break;
+
+			case SAR_SPECIAL:
+				if (tmp != '@' && cidx < 16)
+					COPYCHAR(cmd, cidx, tmp);
+				else if (tmp != '@' && cidx >= 16)
+					state = SAR_ERROR;
+				else
+					state = SAR_WAIT2;
+				break;
+
+			case SAR_WAIT2:
+				if (tmp != '@')
+					state = SAR_ERROR;
+				else {
+					COPYCHAR(cmd, cidx, '\0');
+					if (invoke_repl(post, cmd, repltab))
+						fprintf(post->out, "@@%s@@", cmd);
+					cidx = 0;
+					state = SAR_NORMAL;
+				}
+				break;
+		}
+	}
+
+	if (state == SAR_ERROR)
+		fprintf(post->out, "\n====================\nSAR error!\n");
+
+	if (oidx) {
+		COPYCHAR(obuf, oidx, '\0');
+		fprintf(post->out, obuf);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sar.h	Wed Feb 04 01:14:15 2009 -0500
@@ -0,0 +1,16 @@
+#ifndef __SAR_H
+#define __SAR_H
+
+#include "post.h"
+
+struct repltab_entry {
+	char what[16];
+	void (*f)(struct post*);
+};
+
+extern void sar(struct post *post, char *ibuf, int size,
+		struct repltab_entry *repltab);
+
+struct repltab_entry *repltab_html;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/story.c	Wed Feb 04 01:14:15 2009 -0500
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "post.h"
+#include "sar.h"
+#include "html.h"
+
+int main(int argc, char **argv)
+{
+	struct post post;
+	int ret;
+
+	post.out = stdout;
+
+	fprintf(post.out, "Content-Type: text/html\n\n");
+
+	ret = load_post(30, &post);
+	if (ret) {
+		fprintf(post.out, "Gah! %d\n", ret);
+		return 0;
+	}
+
+	html_header(&post);
+	html_story(&post);
+	html_comments(&post);
+	html_sidebar(&post);
+	html_footer(&post);
+
+	destroy_post(&post);
+
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xattr.c	Wed Feb 04 01:14:15 2009 -0500
@@ -0,0 +1,26 @@
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <attr/xattr.h>
+
+char *safe_getxattr(char *path, char *attr_name)
+{
+	ssize_t size;
+	char *buf;
+
+	size = getxattr(path, attr_name, NULL, 0);
+	if (size == -1)
+		return NULL;
+
+	buf = malloc(size+1);
+	if (!buf)
+		return NULL;
+
+	size = getxattr(path, attr_name, buf, size+1);
+	if (size == -1) {
+		free(buf);
+		return NULL;
+	}
+
+	return buf;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xattr.h	Wed Feb 04 01:14:15 2009 -0500
@@ -0,0 +1,6 @@
+#ifndef __XATTR_H
+#define __XATTR_H
+
+extern char *safe_getxattr(char *path, char *attr_name);
+
+#endif