config parser

This commit is contained in:
Your Name 2025-06-09 04:29:24 +03:00
parent 8e401acc8c
commit ee046a07e6
7 changed files with 163 additions and 30 deletions

View file

@ -2,7 +2,12 @@ CC?=cc
CFLAGS?=-pedantic -Wall -Wextra -s -Os
all:
$(CC) $(CFLAGS) img.c -o 8img
$(CC) -c -I src/ -o obj/db.o src/db.c
$(CC) -c -I src/ -o obj/config.o src/config.c
$(CC) -c -I src/ -o obj/builder.o src/builder.c
$(CC) -c -I src/ -o obj/funcs.o src/funcs.c
$(CC) $(CFLAGS) -I src -o 8img obj/db.o obj/config.o obj/builder.o obj/funcs.o src/main.c
clean:
rm 8img
rm obj/*

6
config
View file

@ -4,17 +4,15 @@ ROOT www
# Html generator
CSS style.css
LOGO logo.png
DESC 8img
TITLE / img
POST_PER_PAGE 5
POSTS_AT_PAGE 5
# RSS generator
LINK https://nlight.tilde.team/img/
XML_FILE index.xml
LANGUAGE en-US
MAX_POST_COUNT 20
MAX_POSTS 20
# Date
DATE_FORMAT %a, %d %h %Y %H:%M:%S %z

0
obj/.gitignore vendored Normal file
View file

View file

@ -25,7 +25,7 @@ char *GetDate(const char *fmt, time_t time) {
}
struct DB_STR *build_html_page(const struct CONFIG cfg, FILE *fp, const char *file, const struct UNIQ_TAGS ut, struct DB_STR *db, const size_t page, const size_t pages) {
fprintf(fp, "<html>\n<head>\n<link rel='stylesheet' href='%s'>\n<title>%s</title>\n<meta charset='UTF-8'>\n</head>\n<body>\n<center><a href='index.html'><img id='logo' src='%s'></a>\n<h1 id='desc'>%s | <a href='%s'>RSS</a><br>%s/p%zu</h1></center>\n", CSS, TITLE, LOGO, DESC, XML_FILE, file, page);
fprintf(fp, "<html>\n<head>\n<link rel='stylesheet' href='%s'>\n<title>%s</title>\n<meta charset='UTF-8'>\n</head>\n<body>\n<center><a href='index.html'><img id='logo' src='%s'></a>\n<h1 id='desc'>%s | <a href='%s'>RSS</a><br>%s/p%zu</h1></center>\n", cfg.css, cfg.title, cfg.logo, cfg.desc, cfg.xml_file, file, page);
/* Tags */
fputs("<center><div class='alltags'>\n<a href='index.html'>all</a>", fp);
@ -150,7 +150,7 @@ void build_xml(const struct CONFIG cfg, struct DB_STR *db) {
return;
/* Header */
fprintf(fp, "<?xml version='1.0' encoding='UTF-8' ?>\n<rss version='2.0' xmlns:atom='http://www.w3.org/2005/Atom'>\n<channel>\n\t<atom:link href='%s' rel='self' type='application/rss+xml' />\n\t<title>%s</title>\n\t<link>%s</link>\n\t<description>%s</description>\n\t<language>%s</language>\n", LINK, TITLE, LINK, DESC, LANGUAGE);
fprintf(fp, "<?xml version='1.0' encoding='UTF-8' ?>\n<rss version='2.0' xmlns:atom='http://www.w3.org/2005/Atom'>\n<channel>\n\t<atom:link href='%s' rel='self' type='application/rss+xml' />\n\t<title>%s</title>\n\t<link>%s</link>\n\t<description>%s</description>\n\t<language>%s</language>\n", cfg.link, cfg.desc, cfg.link, cfg.desc, cfg.language);
/* Content */
size_t count = 0;
@ -161,15 +161,15 @@ void build_xml(const struct CONFIG cfg, struct DB_STR *db) {
/* Post */
fprintf(fp, "\n<item>\n\t<title>%s</title>\n\t<link>%s%s%s</link>\n\t<guid>%s%s%s</guid>\n\t<pubDate>\n\t\t%s\t</pubDate>\n\t<description><![CDATA[\n\t\t<p><img src='%s%s%s' alt='plup'></p>\n\t\t<p>",
bckp->filename,
LINK, CHECK_URL(LINK), bckp->filename,
LINK, CHECK_URL(LINK), bckp->filename,
cfg.link, CHECK_URL(cfg.link), bckp->filename,
cfg.link, CHECK_URL(cfg.link), bckp->filename,
GetDate(cfg.date_fmt, bckp->birthtime),
LINK, CHECK_URL(LINK), bckp->filename);
cfg.link, CHECK_URL(cfg.link), bckp->filename);
/* Tags */
for (size_t i = 0; i < bckp->size; i++)
fprintf(fp, "<a href='%s%s%s.html'> %s</a>&nbsp; ",
LINK, CHECK_URL(LINK), bckp->tags[i],
cfg.link, CHECK_URL(cfg.link), bckp->tags[i],
bckp->tags[i]);
fputs("</p>\n\t]]></description>\n</item>", fp);

View file

@ -1,7 +1,122 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include "funcs.h"
#include "config.h"
int parse_config(struct CONFIG *cfg, const char *cfg_path) {
cfg->root = "www";
void free_cfg(struct CONFIG *cfg) {
char **var1[] = {&cfg->root, &cfg->css, &cfg->logo, &cfg->desc, &cfg->title, &cfg->link, &cfg->xml_file, &cfg->language, &cfg->date_fmt};
char var2[] = {cfg->root_alloc, cfg->css_alloc, cfg->logo_alloc, cfg->desc_alloc, cfg->title_alloc, cfg->link_alloc, cfg->xml_file_alloc, cfg->language_alloc, cfg->date_fmt_alloc};
for (size_t i = 0; i < sizeof(var2); i++)
if (var2[i] && *(var1[i]))
free(*(var1[i]));
}
const char *skip_space(const char *str) {
const char *ptr = str;
while (isspace(*ptr))
ptr++;
return ptr;
}
int add_str(const char *prog_name, char **dst, char *flag, const char *src) {
if (!(*src))
return 1;
*dst = strdup(skip_space(src));
if (*dst == NULL) {
fprintf(stderr, "%s: strdup: %s\n", prog_name, strerror(errno));
return 1;
}
*flag = 1;
return 0;
}
int add_int(const char *prog_name, size_t line, size_t *dst, const char *src) {
char *ptr = "";
*dst = strtoul(skip_space(src), &ptr, 10);
if (*ptr) {
fprintf(stderr, "%s: incorrect number at line %zu: %s\n", prog_name, line, ptr);
return 1;
}
return 0;
}
int parse_config(struct CONFIG *cfg, const char *cfg_path) {
FILE *fp = file_open(cfg->prog_name, cfg_path, "r");
if (fp == NULL)
return 1;
char *str = NULL;
ssize_t bytes = 0;
size_t n = 0;
size_t line = 0;
int ret = 0;
while ((bytes = getline(&str, &n, fp)) > 0 && ret == 0) {
line++;
if (str[0] == '\0' || str[0] == '\n' || str[0] == '#')
continue;
char *ptr = strrchr(str, '\n');
if (ptr != NULL)
*ptr = '\0';
if ((ptr = strstr(str, "ROOT")))
ret = add_str(cfg->prog_name, &cfg->root, &cfg->root_alloc, ptr + sizeof("ROOT"));
else if ((ptr = strstr(str, "CSS")))
ret = add_str(cfg->prog_name, &cfg->css, &cfg->css_alloc, ptr + sizeof("CSS"));
else if ((ptr = strstr(str, "LOGO")))
ret = add_str(cfg->prog_name, &cfg->logo, &cfg->logo_alloc, ptr + sizeof("LOGO"));
else if ((ptr = strstr(str, "DESC")))
ret = add_str(cfg->prog_name, &cfg->desc, &cfg->desc_alloc, ptr + sizeof("DESC"));
else if ((ptr = strstr(str, "TITLE")))
ret = add_str(cfg->prog_name, &cfg->title, &cfg->title_alloc, ptr + sizeof("TITLE"));
else if ((ptr = strstr(str, "LINK")))
ret = add_str(cfg->prog_name, &cfg->link, &cfg->link_alloc, ptr + sizeof("LINK"));
else if ((ptr = strstr(str, "XML_FILE")))
ret = add_str(cfg->prog_name, &cfg->xml_file, &cfg->xml_file_alloc, ptr + sizeof("XML_FILE"));
else if ((ptr = strstr(str, "LANGUAGE")))
ret = add_str(cfg->prog_name, &cfg->language, &cfg->language_alloc, ptr + sizeof("LANGUAGE"));
else if ((ptr = strstr(str, "DATE_FORMAT")))
ret = add_str(cfg->prog_name, &cfg->date_fmt, &cfg->date_fmt_alloc, ptr + sizeof("DATE_FORMAT"));
else if ((ptr = strstr(str, "POSTS_AT_PAGE")))
ret = add_int(cfg->prog_name, line, &cfg->posts_at_page, ptr + sizeof("POSTS_AT_PAGE"));
else if ((ptr = strstr(str, "MAX_POSTS")))
ret = add_int(cfg->prog_name, line, &cfg->max_posts, ptr + sizeof("MAX_POSTS"));
else {
fprintf(stderr, "%s: syntax error on %zu: %s\n", cfg->prog_name, line, str);
ret = 1;
}
}
fclose(fp);
if (str)
free(str);
if (ret) {
fprintf(stderr, "%s: parser error\n", cfg->prog_name);
free_cfg(cfg);
}
return ret;
}

View file

@ -56,25 +56,41 @@ struct CONFIG {
char *prog_name;
char *root;
char root_alloc;
/* HTML */
char *css;
char *logo;
char *desc;
char *title;
size_t posts_at_page;
char css_alloc;
char *logo;
char logo_alloc;
char *desc;
char desc_alloc;
char *title;
char title_alloc;
size_t posts_at_page;
/* RSS */
char *link;
char link_alloc;
char *xml_file;
char xml_file_alloc;
char *language;
char language_alloc;
size_t max_posts;
/* Date format */
char *date_fmt;
char date_fmt_alloc;
};
void free_cfg(struct CONFIG *cfg);
int parse_config(struct CONFIG *cfg, const char *cfg_path);
#endif

View file

@ -11,7 +11,7 @@
struct CONFIG cfg;
void help(void) {
////
free_cfg(&cfg);
printf("%s -[f:d:h] [add/rebuild/version/del]:\n\tadd [img] [tag1] [tag2]...\n\trebuild\n\tversion\n\tdel [image id]\n\nOptions:\n\t-d STR set description\n\t-f STR Path to config file\n\t-h This menu\n", cfg.prog_name);
exit(0);
@ -196,7 +196,7 @@ int main(int argc, char **argv) {
if (chdir(cfg.root) < 0) {
fprintf(stderr, "%s: chdir: %s\n", cfg.prog_name, strerror(errno));
////
free_cfg(&cfg);
return 1;
}
@ -216,12 +216,11 @@ int main(int argc, char **argv) {
ret = rebuild(cfg);
else if (!strcmp(argv[0], "version"))
printf("%s (8img) version: 2.0.1\nWritten under WTFPL License.\n", cfg.prog_name);
printf("%s (8img) version: 2.0.2\nWritten under WTFPL License.\n", cfg.prog_name);
else
help();
////
free_cfg(&cfg);
return ret;
}