commit 4356b42ad6870ba72fc7eb247fff3069591bf6b9
parent 66c61872e8c278b8fb357d80c8bbb965afa38809
Author: Paco Esteban <paco@e1e0.net>
Date: Wed, 17 Jun 2020 16:21:41 +0200
fixing horrors thanks to tracey
Diffstat:
M | Makefile | | | 2 | ++ |
M | helpers.c | | | 66 | +++++++++++++++++++++++++++++++++++++----------------------------- |
M | helpers.h | | | 9 | +++++++-- |
M | ssnail.c | | | 187 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ |
4 files changed, 162 insertions(+), 102 deletions(-)
diff --git a/Makefile b/Makefile
@@ -6,4 +6,6 @@ LDFLAGS += -L/usr/local/lib
LDADD += -llowdown -lm
CFLAGS += -I/usr/local/include -I${.CURDIR}
+DEBUG = -g -O2
+
.include <bsd.prog.mk>
diff --git a/helpers.c b/helpers.c
@@ -16,6 +16,7 @@
#include <sys/stat.h>
#include <sys/syslimits.h>
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -23,16 +24,22 @@
#include "helpers.h"
-int
-build_full_path(char fullpath[PATH_MAX], char *dir, char *file)
+char *
+build_full_path(char *dir, char *file)
{
- // build the full path
- (void)strlcpy(fullpath, dir, PATH_MAX);
- if (fullpath[strlen(fullpath)-2] != '/')
- (void)strlcat(fullpath, "/", PATH_MAX);
- (void)strlcat(fullpath, file, PATH_MAX);
+ int n = 0;
+ char *fullpath = NULL, separator[2] = "";
+
+ /* if user input does not have trailing slash, add it */
+ if (dir[strlen(dir)-1] != '/')
+ strlcat(separator, "/", sizeof(separator));
+
+ n = asprintf(&fullpath, "%s%s%s", dir, separator, file);
+ if ((n < 0) || (n > PATH_MAX)) {
+ return NULL;
+ }
- return 1;
+ return fullpath;
}
int
@@ -47,7 +54,7 @@ copy_file(const char *source_file, const char *dest_file, int force)
return -1;
src_mtime = st.st_mtim.tv_sec;
- if (stat(dest_file, &st) == -1) { // dst file does not have to exist
+ if (stat(dest_file, &st) == -1) { /* dst file does not have to exist */
if (errno != ENOENT)
return -1;
dst_mtime = 0;
@@ -101,9 +108,9 @@ load_from_file(char **buffer, char *path)
return 0;
if (f) {
- fseek(f, 0, SEEK_END); // go to the end of file
- length = ftell(f); // record the length of the file
- fseek(f, 0, SEEK_SET); // go to the start again
+ fseek(f, 0, SEEK_END); /* go to the end of file */
+ length = ftell(f); /* record the length of the file */
+ fseek(f, 0, SEEK_SET); /* go to the start again */
*buffer = malloc(length + 1);
if (*buffer)
fread(*buffer, 1, length, f);
@@ -120,28 +127,29 @@ load_from_file(char **buffer, char *path)
}
char *
-str_rep(const char *s, const char *oldW, const char *newW)
+str_rep(const char *s, const char *old, const char *new)
{
char *r;
int i, cnt = 0;
- int newWlen = strlen(newW);
- int oldWlen = strlen(oldW);
+ int new_len = strlen(new);
+ int old_len = strlen(old);
- if (newWlen == 0 || oldWlen == 0)
+ if (new_len == 0 || old_len == 0)
return NULL;
- // Counting the number of times old word
- // occur in the string
+ /* Counting the number of times old word
+ * occur in the string
+ */
for (i = 0; s[i] != '\0'; i++) {
- if (strstr(&s[i], oldW) == &s[i]) {
+ if (strstr(&s[i], old) == &s[i]) {
cnt++;
- // Jumping to index after the old word.
- i += oldWlen - 1;
+ /* Jumping to index after the old word. */
+ i += old_len - 1;
}
}
- // Making new string long enough
- r = (char *)malloc(i + cnt * (newWlen - oldWlen) + 1);
+ /* Making new string long enough */
+ r = (char *)malloc(i + cnt * (new_len - old_len) + 1);
if (!r) return NULL;
i = 0;
@@ -152,17 +160,17 @@ str_rep(const char *s, const char *oldW, const char *newW)
* of result. Then increment by the lenght so we do not check
* unnecessarily.
*/
- if (strstr(s, oldW) == s) {
+ if (strstr(s, old) == s) {
/*
* On the original example it was done like this:
- * strcpy(&r[i], newW);
+ * strcpy(&r[i], new);
* I think there's no need to dereference and reference
* again.
*/
- strcpy(r+i, newW);
- i += newWlen;
- s += oldWlen;
- } else // if not copy the char and increment pointers
+ strcpy(r+i, new);
+ i += new_len;
+ s += old_len;
+ } else /* if not copy the char and increment pointers */
r[i++] = *s++;
}
diff --git a/helpers.h b/helpers.h
@@ -17,10 +17,15 @@
#ifndef HELPERS_H
#define HELPERS_H
-int build_full_path(char *, char *, char *);
+#define HEADER "_header.html"
+#define FOOTER "_footer.html"
+
int copy_file(const char *, const char *, int);
-const char *get_filename_ext(const char *);
int load_from_file(char **, char *);
+
+const char *get_filename_ext(const char *);
+
+char *build_full_path(char *, char *);
char *str_rep(const char *, const char *, const char *);
#endif /* HELPERS_H */
diff --git a/ssnail.c b/ssnail.c
@@ -18,6 +18,7 @@
#include <sys/stat.h>
#include <sys/syslimits.h>
#include <sys/types.h>
+
#include <dirent.h>
#include <err.h>
#include <errno.h>
@@ -26,7 +27,6 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
-
#include <lowdown.h>
#include "helpers.h"
@@ -34,39 +34,40 @@
#define MAX_META 255
struct article {
+ size_t htmlz;
+ size_t origz;
+
char src_path[PATH_MAX];
char dst_path[PATH_MAX];
char *orig_content;
- size_t origz;
char *html_content;
- size_t htmlz;
char *title;
char *author;
char *date;
char *type;
+
long long src_mtime;
long long dst_mtime;
+
SLIST_ENTRY(article) entries;
};
-struct article *a = NULL;
SLIST_HEAD(listhead, article) head;
-extern char *__progname;
-void articleq_free(struct listhead *);
-int gen_html(struct article *);
-int generate_index(struct listhead *, char *, char *, char *);
-int populate_article_entry(struct article *);
-int process_dir(char[PATH_MAX], char[PATH_MAX], int);
-void usage();
-int write_html(struct article *, char *, char *);
+__dead static void usage(void);
+static void articleq_free(struct listhead *);
+
+static int gen_html(struct article *);
+static int generate_index(struct listhead *, char *, char *, char *);
+static int populate_article_entry(struct article *);
+static int process_dir(char *, char *, int);
+static int write_html(struct article *, char *, char *);
-void
+__dead static void
usage(void)
{
- (void)fprintf(stderr,
- "usage: %s [-F] [-f footer] [-h header] [-i] "
- "src_folder dest_folder\n", __progname);
+ fprintf(stderr, "usage: %s [-F] [-f footer] [-h header] [-i] "
+ "src_folder dst_folder\n", getprogname());
exit(1);
}
@@ -75,12 +76,17 @@ main(int argc, char *argv[])
{
DIR *dirp;
struct dirent *dp;
- int ch, force = 0, index = 0, needs_index = 0;
- char srcdir[PATH_MAX] = "", dstdir[PATH_MAX] = "",
- header_tpl[PATH_MAX] = "./_header.html",
- footer_tpl[PATH_MAX] = "./_footer.html",
- *fbuf = NULL;
struct article *ap = NULL;
+ int ch, force = 0, index = 0, needs_index = 0;
+ char *srcdir = NULL, *dstdir = NULL, *fbuf = NULL;
+ char *header_tpl = NULL, *footer_tpl = NULL;
+
+ header_tpl = strdup(HEADER);
+ if (header_tpl == NULL)
+ return -1;
+ footer_tpl = strdup(FOOTER);
+ if (footer_tpl == NULL)
+ return -1;
while ((ch = getopt(argc, argv, "Ff:h:i")) != -1) {
switch (ch) {
@@ -88,10 +94,16 @@ main(int argc, char *argv[])
force = 1;
break;
case 'f':
- (void)strlcpy(footer_tpl, optarg, PATH_MAX);
+ free(footer_tpl);
+ footer_tpl = strdup(optarg);
+ if (footer_tpl == NULL)
+ return -1;
break;
case 'h':
- (void)strlcpy(header_tpl, optarg, PATH_MAX);
+ free(header_tpl);
+ header_tpl = strdup(FOOTER);
+ if (header_tpl == NULL)
+ return -1;
break;
case 'i':
index = 1;
@@ -103,13 +115,17 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- SLIST_INIT(&head); // init the linked list
- // src and dst dir are mandatory.
+ SLIST_INIT(&head); /* init the linked list */
+ /* src and dst dir are mandatory. */
if (argc < 2)
usage();
- (void)strlcpy(srcdir, argv[0], PATH_MAX);
- (void)strlcpy(dstdir, argv[1], PATH_MAX);
+ srcdir = strdup(argv[0]);
+ if (srcdir == NULL)
+ return -1;
+ dstdir = strdup(argv[1]);
+ if (dstdir == NULL)
+ return -1;
if (process_dir(srcdir, dstdir, force) == -1)
err(1, "cannot process src dir");
@@ -129,14 +145,19 @@ main(int argc, char *argv[])
generate_index(&head, header_tpl, footer_tpl, dstdir);
}
+ free(srcdir);
+ free(dstdir);
+ free(fbuf);
+ free(header_tpl);
+ free(footer_tpl);
articleq_free(&head);
return 0;
}
-int
-generate_index(struct listhead *h, char head_tpl[PATH_MAX],
- char foot_tpl[PATH_MAX], char *dst_dir)
+static int
+generate_index(struct listhead *h, char *head_tpl,
+ char *foot_tpl, char *dst_dir)
{
struct article *a;
char *header = NULL, *footer = NULL;
@@ -144,24 +165,28 @@ generate_index(struct listhead *h, char head_tpl[PATH_MAX],
int r = -1;
time_t now;
struct tm *timeInfo;
- char mytime[12], index_path[PATH_MAX];
+ char mytime[12], *index_path = NULL;
time(&now);
timeInfo = localtime(&now);
strftime(mytime, sizeof(mytime), "%Y-%m-%d", timeInfo);
- load_from_file(&header, head_tpl);
+ if (load_from_file(&header, head_tpl) == 0)
+ goto out;
+ /* XXX: 13. here is where you would null term *header = '\0' */
header = str_rep(header, "$title$", "index");
header = str_rep(header, "$author$", getlogin());
header = str_rep(header, "$date$", mytime);
- load_from_file(&footer, foot_tpl);
+ if (load_from_file(&footer, foot_tpl) == 0)
+ goto out;
footer = str_rep(footer, "$title$", "index");
- build_full_path(index_path, dst_dir, "index.html");
+ if ((index_path = build_full_path(dst_dir, "index.html")) == NULL)
+ goto out;
if ((fout = fopen(index_path, "w")) == NULL)
goto out;
fwrite(header, 1, strlen(header), fout);
- // TODO: make this list reverse date ordered
+ /* TODO: make this list reverse date ordered */
fprintf(fout, "<ul>\n");
SLIST_FOREACH(a, h, entries) {
if (strcmp(a->type, "article") == 0) {
@@ -176,13 +201,14 @@ generate_index(struct listhead *h, char head_tpl[PATH_MAX],
r = 0;
out:
+ free(index_path);
free(header);
free(footer);
return r;
}
-void
+static void
articleq_free(struct listhead *h)
{
struct article *a;
@@ -194,11 +220,12 @@ articleq_free(struct listhead *h)
free(a->title);
free(a->author);
free(a->date);
+ free(a->type);
free(a);
}
}
-int
+static int
gen_html(struct article *a)
{
struct lowdown_opts opts;
@@ -207,8 +234,8 @@ gen_html(struct article *a)
int r = 0;
size_t orig_size = 0;
- TAILQ_INIT(&mq); // create the queue(linked list) of lowdown_meta
- memset(&opts, 0, sizeof(struct lowdown_opts)); // init opts to 0
+ TAILQ_INIT(&mq); /* create the queue(linked list) of lowdown_meta */
+ memset(&opts, 0, sizeof(struct lowdown_opts)); /* init opts to 0 */
opts.maxdepth = 128;
opts.type = LOWDOWN_HTML;
@@ -225,30 +252,32 @@ gen_html(struct article *a)
LOWDOWN_HTML_OWASP |
LOWDOWN_HTML_SKIP_HTML;
- // use strlen(orig) here because the of the \0 char that
- // was showing up on the dest buffer.
- // playing with origz did not work here.
+ /* use strlen(orig) here because the of the \0 char that
+ * was showing up on the dest buffer.
+ * playing with origz did not work here.
+ */
lowdown_buf(&opts, a->orig_content, strlen(a->orig_content),
&a->html_content, &a->htmlz, &mq);
+ /* set default values for metadata */
+ a->title = strdup("");
+ a->author = strdup("");
+ a->date = strdup("");
+ a->type = strdup("page");
+
+ /* collect metadata from markdown */
TAILQ_FOREACH(md, &mq, entries) {
- size_t valz = (strlen(md->value) > MAX_META)
- ? MAX_META : strlen(md->value) + 1;
if (strcmp(md->key, "title") == 0 ) {
- a->title = malloc(valz);
- (void)strlcpy(a->title, md->value, valz);
+ asprintf(&a->title, "%s", md->value);
}
if (strcmp(md->key, "author") == 0 ) {
- a->author = malloc(valz);
- (void)strlcpy(a->author, md->value, valz);
+ asprintf(&a->author, "%s", md->value);
}
if (strcmp(md->key, "date") == 0 ) {
- a->date = malloc(valz);
- (void)strlcpy(a->date, md->value, valz);
+ asprintf(&a->date, "%s", md->value);
}
if (strcmp(md->key, "type") == 0 ) {
- a->type = malloc(valz);
- (void)strlcpy(a->type, md->value, valz);
+ asprintf(&a->type, "%s", md->value);
}
}
@@ -260,13 +289,19 @@ out:
return r;
}
-int
-write_html(struct article *ap, char head_tpl[PATH_MAX], char foot_tpl[PATH_MAX])
+static int
+write_html(struct article *ap, char *head_tpl, char *foot_tpl)
{
char *header = NULL, *footer = NULL;
FILE *fout;
int r = -1;
+/*
+ * XXX: 15. need error handling below. This is where the segfault is, because I
+ * don't have the required article struct filled. So, without pouring over
+ * everything you've written, I'm obviously missing something in a file
+ * somewhere. :D
+ */
if (strlen(ap->title) == 0
|| strlen(ap->author) == 0
|| strlen(ap->date) == 0)
@@ -295,7 +330,7 @@ out:
return r;
}
-int
+static int
populate_article_entry(struct article *ap)
{
struct stat st;
@@ -306,7 +341,7 @@ populate_article_entry(struct article *ap)
goto out;
ap->src_mtime = st.st_mtim.tv_sec;
- if (stat(ap->dst_path, &st) == -1) { // dst file does not have to exist
+ if (stat(ap->dst_path, &st) == -1) { /* dst file does not have to exist */
if (errno != ENOENT)
goto out;
ap->dst_mtime = 0;
@@ -323,20 +358,24 @@ out:
return retval;
}
-int
-process_dir(char orig[PATH_MAX], char dest[PATH_MAX], int force)
+static int
+process_dir(char *src, char *dst, int force)
{
DIR *dirp;
struct dirent *dp;
struct stat st;
+ struct article *a = NULL;
+
int retval = -1;
- if (stat(dest, &st) == -1 && errno == ENOENT) {
- if (mkdir(dest, 0755) == -1)
+ char *src_path = NULL, *dst_path = NULL;
+
+ if (stat(dst, &st) == -1 && errno == ENOENT) {
+ if (mkdir(dst, 0755) == -1)
return -1;
}
- if ((dirp = opendir(orig)) == NULL)
+ if ((dirp = opendir(src)) == NULL)
return -1;
while ((dp = readdir(dirp)) != NULL) {
@@ -344,40 +383,46 @@ process_dir(char orig[PATH_MAX], char dest[PATH_MAX], int force)
|| strcmp(dp->d_name, "..") == 0)
continue;
- char orig_path[PATH_MAX], dest_path[PATH_MAX];
-
- if (build_full_path(orig_path, orig, dp->d_name) == -1)
+ if ((src_path = build_full_path(src, dp->d_name)) == NULL)
goto out;
- if (build_full_path(dest_path, dest, dp->d_name) == -1)
+ if ((dst_path = build_full_path(dst, dp->d_name)) == NULL)
goto out;
if (dp->d_type == DT_REG) {
- if (strcmp(get_filename_ext(orig_path), "md") == 0) {
+ if (strcmp(get_filename_ext(src_path), "md") == 0) {
char *fbuf = NULL;
+ int n = 0;
+
a = malloc(sizeof(struct article));
- (void)strlcpy(a->src_path, orig_path, PATH_MAX);
- fbuf = str_rep(dest_path, ".md", ".html");
- (void)strlcpy(a->dst_path, fbuf, PATH_MAX);
+ strlcpy(a->src_path, src_path, PATH_MAX);
+ fbuf = str_rep(dst_path, ".md", ".html");
+ strlcpy(a->dst_path, fbuf, PATH_MAX);
free(fbuf);
if((populate_article_entry(a) == -1))
err(2, "cannot populate article");
SLIST_INSERT_HEAD(&head, a, entries);
} else {
- if (copy_file(orig_path, dest_path, force) == -1)
+ if (copy_file(src_path, dst_path, force) == -1)
goto out;
}
}
if (dp->d_type == DT_DIR) {
- if (process_dir(orig_path, dest_path, force) == -1)
+ if (process_dir(src_path, dst_path, force) == -1)
goto out;
}
+ free(src_path);
+ free(dst_path);
+ src_path = NULL;
+ dst_path = NULL;
}
retval = 0;
out:
+ free(src_path);
+ free(dst_path);
closedir(dirp);
return retval;
}