summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAli Fardan <raiz@stellarbound.space>2020-11-04 09:53:05 +0300
committerAli Fardan <raiz@stellarbound.space>2020-11-04 09:53:05 +0300
commitb9b2ae68e26ef1b1b033d4231f8d7e53244cebff (patch)
tree8210c5f1c55ada6491f8bef2b7d13fdff99c5612
parent7ddf10843fa6c5247a809824344d391d7729fc73 (diff)
downloadgemlog-b9b2ae68e26ef1b1b033d4231f8d7e53244cebff.tar.gz
implement gemtext index generator
-rw-r--r--.gitignore1
-rw-r--r--Makefile2
-rw-r--r--gemlog.h3
-rw-r--r--index_gmi.c185
-rw-r--r--main.c13
5 files changed, 201 insertions, 3 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..34e3a08
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+blog
diff --git a/Makefile b/Makefile
index 100e062..9036784 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ OUT = gemlog
 
 PREFIX = /usr
 
-OBJS = gemlog.o html.o free.o main.o strlcpy.o strlcat.o
+OBJS = gemlog.o html.o index_gmi.o free.o main.o strlcpy.o strlcat.o
 MANPAGES = 
 
 all: $(OUT)
diff --git a/gemlog.h b/gemlog.h
index e74058b..e9cefa0 100644
--- a/gemlog.h
+++ b/gemlog.h
@@ -20,6 +20,9 @@ struct gemlog_entry **gemlog_readdir(const char *);
 /* html.c */
 int gemlog_write_html(struct gemlog_entry **, const char *);
 
+/* index_gmi.c */
+int gemlog_write_index(struct gemlog_entry **, const char *);
+
 /* free.c */
 void gemlog_entry_free(struct gemlog_entry *);
 void gemlog_entry_list_free(struct gemlog_entry **);
diff --git a/index_gmi.c b/index_gmi.c
new file mode 100644
index 0000000..7f16a42
--- /dev/null
+++ b/index_gmi.c
@@ -0,0 +1,185 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <gemtext.h>
+
+#include "gemlog.h"
+
+static int
+find_latest_year(struct gemlog_entry **feed)
+{
+	int i;
+	int ret;
+
+	ret = 0;
+	for (i = 0; feed[i] != NULL; i++) {
+		if (feed[i]->date.tm_year > ret)
+			ret = feed[i]->date.tm_year;
+	}
+	return ret;
+}
+
+static int
+find_latest_month(struct gemlog_entry **feed, int year)
+{
+	int i;
+	int ret;
+
+	ret = 0;
+	for (i = 0; feed[i] != NULL; i++) {
+		if (feed[i]->date.tm_year == year) {
+			if (feed[i]->date.tm_mon > ret)
+				ret = feed[i]->date.tm_mon;
+		}
+	}
+	return ret;
+}
+
+static int
+find_latest_day(struct gemlog_entry **feed, int year, int month)
+{
+	int i;
+	int ret;
+
+	ret = 0;
+	for (i = 0; feed[i] != NULL; i++) {
+		if (feed[i]->date.tm_year == year && feed[i]->date.tm_mon == month) {
+			if (feed[i]->date.tm_mday > ret)
+				ret = feed[i]->date.tm_mday;
+		}
+	}
+	return ret;
+}
+
+static int
+find_latest_hour(struct gemlog_entry **feed, int year, int month, int day)
+{
+	int i;
+	int ret;
+
+	ret = 0;
+	for (i = 0; feed[i] != NULL; i++) {
+		if (feed[i]->date.tm_year == year && feed[i]->date.tm_mon == month && feed[i]->date.tm_mday == day) {
+			if (feed[i]->date.tm_hour > ret)
+				ret = feed[i]->date.tm_hour;
+		}
+	}
+	return ret;
+}
+
+static int
+gemlog_write_index_hour(struct gemlog_entry **feed, int fd, int year, int month, int day, int hour)
+{
+	int i;
+	int labellen;
+	char *labelbuf;
+	char timestamp[11]; /* 1990-01-01\0 */
+	char pathbuf[PATH_MAX+1];
+	struct gemtext *out;
+
+	labellen = 0;
+
+	for (i = 0; feed[i] != NULL; i++) {
+		if (feed[i]->date.tm_year == year
+		 && feed[i]->date.tm_mon  == month
+		 && feed[i]->date.tm_mday == day
+		 && feed[i]->date.tm_hour == hour) {
+			strftime(timestamp, sizeof(timestamp), "%F", &(feed[i]->date));
+			labellen += strlen(timestamp);
+			labellen += 2; /* ": " */
+			labellen += strlen(feed[i]->title);
+			labelbuf = malloc(labellen+1);
+			if (labelbuf == NULL)
+				return -1;
+			strlcpy(labelbuf, timestamp, labellen+1);
+			strlcat(labelbuf, ": ", labellen+1);
+			strlcat(labelbuf, feed[i]->title, labellen+1);
+			snprintf(pathbuf, sizeof(pathbuf), "%d/%d/%d/%d/%s", year+1900, month+1, day, hour, GEMLOG_CONTENT_FILENAME);
+			out = gemtext_link_new(pathbuf, labelbuf);
+			free(labelbuf);
+			if (out == NULL)
+				return -1;
+			if (gemtext_encode_fd(out, fd) == -1) {
+				gemtext_free(out);
+				return -1;
+			}
+			gemtext_free(out);
+			if (write(fd, "\n", strlen("\n")) == -1)
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int
+gemlog_write_index_day(struct gemlog_entry **feed, int fd, int year, int month, int day)
+{
+	int hour;
+
+	for (hour = find_latest_hour(feed, year, month, day); hour != 0; hour--) {
+		if (gemlog_write_index_hour(feed, fd, year, month, day, hour) == -1)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int
+gemlog_write_index_month(struct gemlog_entry **feed, int fd, int year, int month)
+{
+	int day;
+
+	for (day = find_latest_day(feed, year, month); day != 0; day--) {
+		if (gemlog_write_index_day(feed, fd, year, month, day) == -1)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int
+gemlog_write_index_year(struct gemlog_entry **feed, int fd, int year)
+{
+	int month;
+
+	for (month = find_latest_month(feed, year); month != 0; month--) {
+		if (gemlog_write_index_month(feed, fd, year, month) == -1)
+			return -1;
+	}
+
+	return 0;
+}
+
+int
+gemlog_write_index(struct gemlog_entry **feed, const char *path)
+{
+	int year;
+	int fd;
+
+	fd = open(path, O_WRONLY|O_CREAT|O_TRUNC);
+	if (fd == -1)
+		return -1;
+	if (chmod(path, 0644) == -1) {
+		close(fd);
+		return -1;
+	}
+
+	for (year = find_latest_year(feed); year != 0; year--) {
+		if (gemlog_write_index_year(feed, fd, year) == -1) {
+			close(fd);
+			return -1;
+		}
+	}
+
+	close(fd);
+	return 0;
+}
diff --git a/main.c b/main.c
index 713fcae..fd0c64a 100644
--- a/main.c
+++ b/main.c
@@ -25,12 +25,14 @@ main(int argc, char *argv[])
 	struct gemlog_entry **log;
 	char *aflag;
 	char *hflag;
+	char *iflag;
 	int ch;
 
 	aflag = NULL;
 	hflag = NULL;
+	iflag = NULL;
 
-	while ((ch = getopt(argc, argv, "a:h:")) != -1) {
+	while ((ch = getopt(argc, argv, "a:h:i:")) != -1) {
 		switch (ch) {
 		case 'a':
 			aflag = optarg;
@@ -38,6 +40,9 @@ main(int argc, char *argv[])
 		case 'h':
 			hflag = optarg;
 			break;
+		case 'i':
+			iflag = optarg;
+			break;
 		default:
 			fprintf(stderr, "Usage: %s [-a file] [-h path] path\n", argv[0]);
 			return 1;
@@ -53,7 +58,7 @@ main(int argc, char *argv[])
 	if (log == NULL)
 		err(1, "gemlog_readdir");
 
-	if (!aflag && !hflag)
+	if (!aflag && !hflag && !iflag)
 		_print_gemlog(log);
 
 //	if (aflag) {
@@ -64,6 +69,10 @@ main(int argc, char *argv[])
 		if (gemlog_write_html(log, hflag) == -1)
 			err(1, "gemlog_write_html");
 	}
+	if (iflag) {
+		if (gemlog_write_index(log, iflag) == -1)
+			err(1, "gemlog_write_index");
+	}
 
 	gemlog_entry_list_free(log);
 	return 0;