Refactoring

This commit is contained in:
Armin Friedl 2020-08-30 08:43:10 +02:00
parent a22ac176ca
commit bd51ff593d
4 changed files with 219 additions and 218 deletions

117
dirl.c
View file

@ -31,59 +31,10 @@ suffix(int t)
return ""; return "";
} }
static char*
dirl_read(char* tpl)
{
FILE* tpl_fp;
if (!(tpl_fp = fopen(tpl, "r"))) {
return NULL;
}
/* Get size of template */
if (fseek(tpl_fp, 0L, SEEK_END) < 0) {
fclose(tpl_fp);
return NULL;
}
long tpl_size;
if ((tpl_size = ftell(tpl_fp)) < 0) {
fclose(tpl_fp);
return NULL;
}
rewind(tpl_fp);
/* Read template into tpl_buf */
char* tpl_buf = (char*)calloc(sizeof(char), tpl_size);
if (tpl_buf == NULL) {
fclose(tpl_fp);
free(tpl_buf);
return NULL;
}
if (fread(tpl_buf, 1, tpl_size, tpl_fp) < tpl_size) {
if (feof(tpl_fp)) {
warn("Reached end of template %s prematurely", tpl);
} else if (ferror(tpl_fp)) {
warn("Error while reading template %s", tpl);
}
fclose(tpl_fp);
free(tpl_buf);
clearerr(tpl_fp);
return NULL;
}
return tpl_buf;
}
/* Try to find templates up until root /* Try to find templates up until root
* *
* Iterates the directory hierarchy upwards. Returns the closest path containing * Iterates the directory hierarchy upwards. Returns the closest path containing
* a template file or NULL if none could be found. * one of the template files or NULL if none could be found.
* *
* Note that we are chrooted. * Note that we are chrooted.
*/ */
@ -115,52 +66,47 @@ dirl_find_templ_dir(const char* start_path)
return NULL; return NULL;
} }
/* Helper function to fill template from base+name if file exists */
static void
dirl_fill_templ(char** templ, char* base, char* name, char* def)
{
char* path = calloc(sizeof(char), strlen(base) + strlen(name));
strcpy(path, base);
strcat(path, name);
char* file_buf = read_file(path);
free(path);
if (file_buf) {
*templ = file_buf;
} else {
*templ = def;
}
}
struct dirl_templ struct dirl_templ
dirl_read_templ(const char* path) dirl_read_templ(const char* path)
{ {
struct dirl_templ templates = { .header = DIRL_HEADER_DEFAULT, struct dirl_templ templ;
.entry = DIRL_ENTRY_DEFAULT,
.footer = DIRL_FOOTER_DEFAULT };
char* templ_dir = dirl_find_templ_dir(path); char* templ_dir = dirl_find_templ_dir(path);
char* header_file = dirl_fill_templ(&templ.header, templ_dir, DIRL_HEADER, DIRL_HEADER_DEFAULT);
calloc(sizeof(char), strlen(templ_dir) + strlen(DIRL_HEADER)); dirl_fill_templ(&templ.entry, templ_dir, DIRL_ENTRY, DIRL_ENTRY_DEFAULT);
strcpy(header_file, templ_dir); dirl_fill_templ(&templ.footer, templ_dir, DIRL_FOOTER, DIRL_FOOTER_DEFAULT);
strcat(header_file, DIRL_HEADER);
char* header = dirl_read(header_file);
if (header)
templates.header = header;
free(header_file);
char* entry_file =
calloc(sizeof(char), strlen(templ_dir) + strlen(DIRL_ENTRY));
strcpy(entry_file, templ_dir);
strcat(entry_file, DIRL_ENTRY);
char* entry = dirl_read(entry_file);
if (entry)
templates.entry = entry;
free(entry_file);
char* footer_file =
calloc(sizeof(char), strlen(templ_dir) + strlen(DIRL_FOOTER));
strcpy(footer_file, templ_dir);
strcat(footer_file, DIRL_FOOTER);
char* footer = dirl_read(footer_file);
if (footer)
templates.footer = footer;
free(footer_file);
free(templ_dir); free(templ_dir);
return templates; return templ;
} }
enum status enum status
dirl_header(int fd, const struct response* res, const struct dirl_templ* templ) dirl_header(int fd, const struct response* res, const struct dirl_templ* templ)
{ {
/* Replace placeholder */ /* Replace placeholder */
char* nhead = replace(templ->header, "{curdir}", "something"); char* nhead = calloc(sizeof(char), strlen(templ->header));
memcpy(nhead, templ->header, strlen(templ->header));
replace(&nhead, "{curdir}", res->path);
/* Write header */ /* Write header */
write(fd, nhead, strlen(nhead)); write(fd, nhead, strlen(nhead));
@ -175,7 +121,10 @@ enum status
dirl_entry(int fd, const struct dirent* entry, const struct dirl_templ* templ) dirl_entry(int fd, const struct dirent* entry, const struct dirl_templ* templ)
{ {
/* Replace placeholder */ /* Replace placeholder */
char* nentry = replace(templ->entry, "{entry}", entry->d_name); char* nentry = calloc(sizeof(char), strlen(templ->entry));
memcpy(nentry, templ->entry, strlen(templ->entry));
replace(&nentry, "{entry}", entry->d_name);
replace(&nentry, "{suffix}", suffix(entry->d_type));
/* Write entry */ /* Write entry */
write(fd, nentry, strlen(nentry)); write(fd, nentry, strlen(nentry));
@ -189,7 +138,9 @@ enum status
dirl_footer(int fd, const struct dirl_templ* templ) dirl_footer(int fd, const struct dirl_templ* templ)
{ {
/* Replace placeholder */ /* Replace placeholder */
char* nfoot = replace(templ->footer, "{idx}", "something"); char* nfoot = calloc(sizeof(char), strlen(templ->footer));
memcpy(nfoot, templ->footer, strlen(templ->footer));
replace(&nfoot, "{idx}", "something");
/* Write footer */ /* Write footer */
write(fd, nfoot, strlen(nfoot)); write(fd, nfoot, strlen(nfoot));

8
dirl.h
View file

@ -30,7 +30,7 @@
#define DIRL_ENTRY_DEFAULT \ #define DIRL_ENTRY_DEFAULT \
" <br />\n" \ " <br />\n" \
" <a href=\"{entry}\">{entry}</a>\n" " <a href=\"{entry}\">{entry}{suffix}</a>\n"
#define DIRL_FOOTER_DEFAULT \ #define DIRL_FOOTER_DEFAULT \
" </body>\n" \ " </body>\n" \
@ -38,9 +38,9 @@
struct dirl_templ struct dirl_templ
{ {
const char* header; char* header;
const char* entry; char* entry;
const char* footer; char* footer;
}; };
struct dirl_templ struct dirl_templ

309
util.c
View file

@ -20,162 +20,162 @@ char *argv0;
static void static void
verr(const char *fmt, va_list ap) verr(const char *fmt, va_list ap)
{ {
if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) { if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
fprintf(stderr, "%s: ", argv0); fprintf(stderr, "%s: ", argv0);
} }
vfprintf(stderr, fmt, ap); vfprintf(stderr, fmt, ap);
if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
fputc(' ', stderr); fputc(' ', stderr);
perror(NULL); perror(NULL);
} else { } else {
fputc('\n', stderr); fputc('\n', stderr);
} }
} }
void void
warn(const char *fmt, ...) warn(const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
verr(fmt, ap); verr(fmt, ap);
va_end(ap); va_end(ap);
} }
void void
die(const char *fmt, ...) die(const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
verr(fmt, ap); verr(fmt, ap);
va_end(ap); va_end(ap);
exit(1); exit(1);
} }
void void
epledge(const char *promises, const char *execpromises) epledge(const char *promises, const char *execpromises)
{ {
(void)promises; (void)promises;
(void)execpromises; (void)execpromises;
#ifdef __OpenBSD__ #ifdef __OpenBSD__
if (pledge(promises, execpromises) == -1) { if (pledge(promises, execpromises) == -1) {
die("pledge:"); die("pledge:");
} }
#endif /* __OpenBSD__ */ #endif /* __OpenBSD__ */
} }
void void
eunveil(const char *path, const char *permissions) eunveil(const char *path, const char *permissions)
{ {
(void)path; (void)path;
(void)permissions; (void)permissions;
#ifdef __OpenBSD__ #ifdef __OpenBSD__
if (unveil(path, permissions) == -1) { if (unveil(path, permissions) == -1) {
die("unveil:"); die("unveil:");
} }
#endif /* __OpenBSD__ */ #endif /* __OpenBSD__ */
} }
int int
timestamp(char *buf, size_t len, time_t t) timestamp(char *buf, size_t len, time_t t)
{ {
struct tm tm; struct tm tm;
if (gmtime_r(&t, &tm) == NULL || if (gmtime_r(&t, &tm) == NULL ||
strftime(buf, len, "%a, %d %b %Y %T GMT", &tm) == 0) { strftime(buf, len, "%a, %d %b %Y %T GMT", &tm) == 0) {
return 1; return 1;
} }
return 0; return 0;
} }
int int
esnprintf(char *str, size_t size, const char *fmt, ...) esnprintf(char *str, size_t size, const char *fmt, ...)
{ {
va_list ap; va_list ap;
int ret; int ret;
va_start(ap, fmt); va_start(ap, fmt);
ret = vsnprintf(str, size, fmt, ap); ret = vsnprintf(str, size, fmt, ap);
va_end(ap); va_end(ap);
return (ret < 0 || (size_t)ret >= size); return (ret < 0 || (size_t)ret >= size);
} }
int int
prepend(char *str, size_t size, const char *prefix) prepend(char *str, size_t size, const char *prefix)
{ {
size_t len = strlen(str), prefixlen = strlen(prefix); size_t len = strlen(str), prefixlen = strlen(prefix);
if (len + prefixlen + 1 > size) { if (len + prefixlen + 1 > size) {
return 1; return 1;
} }
memmove(str + prefixlen, str, len + 1); memmove(str + prefixlen, str, len + 1);
memcpy(str, prefix, prefixlen); memcpy(str, prefix, prefixlen);
return 0; return 0;
} }
void void
html_escape(const char *src, char *dst, size_t dst_siz) html_escape(const char *src, char *dst, size_t dst_siz)
{ {
const struct { const struct {
char c; char c;
char *s; char *s;
} escape[] = { } escape[] = {
{ '&', "&amp;" }, { '&', "&amp;" },
{ '<', "&lt;" }, { '<', "&lt;" },
{ '>', "&gt;" }, { '>', "&gt;" },
{ '"', "&quot;" }, { '"', "&quot;" },
{ '\'', "&#x27;" }, { '\'', "&#x27;" },
}; };
size_t i, j, k, esclen; size_t i, j, k, esclen;
for (i = 0, j = 0; src[i] != '\0'; i++) { for (i = 0, j = 0; src[i] != '\0'; i++) {
for (k = 0; k < LEN(escape); k++) { for (k = 0; k < LEN(escape); k++) {
if (src[i] == escape[k].c) { if (src[i] == escape[k].c) {
break; break;
} }
} }
if (k == LEN(escape)) { if (k == LEN(escape)) {
/* no escape char at src[i] */ /* no escape char at src[i] */
if (j == dst_siz - 1) { if (j == dst_siz - 1) {
/* silent truncation */ /* silent truncation */
break; break;
} else { } else {
dst[j++] = src[i]; dst[j++] = src[i];
} }
} else { } else {
/* escape char at src[i] */ /* escape char at src[i] */
esclen = strlen(escape[k].s); esclen = strlen(escape[k].s);
if (j >= dst_siz - esclen) { if (j >= dst_siz - esclen) {
/* silent truncation */ /* silent truncation */
break; break;
} else { } else {
memcpy(&dst[j], escape[k].s, esclen); memcpy(&dst[j], escape[k].s, esclen);
j += esclen; j += esclen;
} }
} }
} }
dst[j] = '\0'; dst[j] = '\0';
} }
char* void
replace(const char *src, const char *old, const char* new) { replace(char **src, const char *old, const char* new) {
int old_len = strlen(old); int old_len = strlen(old);
int new_len = strlen(new); int new_len = strlen(new);
int src_len = strlen(src); int src_len = strlen(*src);
/* Count needed replacements */ /* Count needed replacements */
const char* tmp = src; const char* tmp = *src;
int replc=0; int replc=0;
while ((tmp=strstr(tmp, old))) { while ((tmp=strstr(tmp, old))) {
replc++; replc++;
@ -186,8 +186,8 @@ replace(const char *src, const char *old, const char* new) {
char *buf = calloc( sizeof(char), src_len + replc*(abs(new_len-old_len)) + 1); char *buf = calloc( sizeof(char), src_len + replc*(abs(new_len-old_len)) + 1);
/* Now start replacing */ /* Now start replacing */
const char *srcidx = src; const char *srcidx = *src;
const char *srcidx_old = src; const char *srcidx_old = *src;
char *bufidx = buf; char *bufidx = buf;
while (replc--) { while (replc--) {
@ -202,7 +202,56 @@ replace(const char *src, const char *old, const char* new) {
strncpy(bufidx, srcidx, strlen(srcidx)); // copy tail strncpy(bufidx, srcidx, strlen(srcidx)); // copy tail
return buf; free(*src);
*src = buf;
}
char*
read_file(const char* path){
FILE* tpl_fp;
if (!(tpl_fp = fopen(path, "r"))) {
return NULL;
}
/* Get size of template */
if (fseek(tpl_fp, 0L, SEEK_END) < 0) {
fclose(tpl_fp);
return NULL;
}
long tpl_size;
if ((tpl_size = ftell(tpl_fp)) < 0) {
fclose(tpl_fp);
return NULL;
}
rewind(tpl_fp);
/* Read template into tpl_buf */
char* tpl_buf = (char*)calloc(sizeof(char), tpl_size);
if (tpl_buf == NULL) {
fclose(tpl_fp);
free(tpl_buf);
return NULL;
}
if (fread(tpl_buf, 1, tpl_size, tpl_fp) < tpl_size) {
if (feof(tpl_fp)) {
warn("Reached end of file %s prematurely", path);
} else if (ferror(tpl_fp)) {
warn("Error while reading file %s", path);
}
fclose(tpl_fp);
free(tpl_buf);
clearerr(tpl_fp);
return NULL;
}
return tpl_buf;
} }
#define INVALID 1 #define INVALID 1
@ -213,39 +262,39 @@ long long
strtonum(const char *numstr, long long minval, long long maxval, strtonum(const char *numstr, long long minval, long long maxval,
const char **errstrp) const char **errstrp)
{ {
long long ll = 0; long long ll = 0;
int error = 0; int error = 0;
char *ep; char *ep;
struct errval { struct errval {
const char *errstr; const char *errstr;
int err; int err;
} ev[4] = { } ev[4] = {
{ NULL, 0 }, { NULL, 0 },
{ "invalid", EINVAL }, { "invalid", EINVAL },
{ "too small", ERANGE }, { "too small", ERANGE },
{ "too large", ERANGE }, { "too large", ERANGE },
}; };
ev[0].err = errno; ev[0].err = errno;
errno = 0; errno = 0;
if (minval > maxval) { if (minval > maxval) {
error = INVALID; error = INVALID;
} else { } else {
ll = strtoll(numstr, &ep, 10); ll = strtoll(numstr, &ep, 10);
if (numstr == ep || *ep != '\0') if (numstr == ep || *ep != '\0')
error = INVALID; error = INVALID;
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
error = TOOSMALL; error = TOOSMALL;
else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
error = TOOLARGE; error = TOOLARGE;
} }
if (errstrp != NULL) if (errstrp != NULL)
*errstrp = ev[error].errstr; *errstrp = ev[error].errstr;
errno = ev[error].err; errno = ev[error].err;
if (error) if (error)
ll = 0; ll = 0;
return ll; return ll;
} }
/* /*
@ -257,10 +306,10 @@ strtonum(const char *numstr, long long minval, long long maxval,
void * void *
reallocarray(void *optr, size_t nmemb, size_t size) reallocarray(void *optr, size_t nmemb, size_t size)
{ {
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) { nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM; errno = ENOMEM;
return NULL; return NULL;
} }
return realloc(optr, size * nmemb); return realloc(optr, size * nmemb);
} }

3
util.h
View file

@ -53,7 +53,8 @@ int timestamp(char *, size_t, time_t);
int esnprintf(char *, size_t, const char *, ...); int esnprintf(char *, size_t, const char *, ...);
int prepend(char *, size_t, const char *); int prepend(char *, size_t, const char *);
void html_escape(const char *, char *, size_t); void html_escape(const char *, char *, size_t);
char *replace(const char *, const char *, const char *); void replace(char **, const char *, const char *);
char *read_file(const char* path);
void *reallocarray(void *, size_t, size_t); void *reallocarray(void *, size_t, size_t);
long long strtonum(const char *, long long, long long, const char **); long long strtonum(const char *, long long, long long, const char **);