diff --git a/dirl.c b/dirl.c index 711b3c8..900ecd0 100644 --- a/dirl.c +++ b/dirl.c @@ -31,59 +31,10 @@ suffix(int t) 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 * * 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. */ @@ -115,52 +66,47 @@ dirl_find_templ_dir(const char* start_path) 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 dirl_read_templ(const char* path) { - struct dirl_templ templates = { .header = DIRL_HEADER_DEFAULT, - .entry = DIRL_ENTRY_DEFAULT, - .footer = DIRL_FOOTER_DEFAULT }; + struct dirl_templ templ; char* templ_dir = dirl_find_templ_dir(path); - char* header_file = - calloc(sizeof(char), strlen(templ_dir) + strlen(DIRL_HEADER)); - strcpy(header_file, templ_dir); - 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); + dirl_fill_templ(&templ.header, templ_dir, DIRL_HEADER, DIRL_HEADER_DEFAULT); + dirl_fill_templ(&templ.entry, templ_dir, DIRL_ENTRY, DIRL_ENTRY_DEFAULT); + dirl_fill_templ(&templ.footer, templ_dir, DIRL_FOOTER, DIRL_FOOTER_DEFAULT); free(templ_dir); - return templates; + return templ; } enum status dirl_header(int fd, const struct response* res, const struct dirl_templ* templ) { /* 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(fd, nhead, strlen(nhead)); @@ -175,7 +121,10 @@ enum status dirl_entry(int fd, const struct dirent* entry, const struct dirl_templ* templ) { /* 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(fd, nentry, strlen(nentry)); @@ -189,7 +138,9 @@ enum status dirl_footer(int fd, const struct dirl_templ* templ) { /* 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(fd, nfoot, strlen(nfoot)); diff --git a/dirl.h b/dirl.h index 5b6478c..b374c01 100644 --- a/dirl.h +++ b/dirl.h @@ -30,7 +30,7 @@ #define DIRL_ENTRY_DEFAULT \ "
\n" \ - " {entry}\n" + " {entry}{suffix}\n" #define DIRL_FOOTER_DEFAULT \ " \n" \ @@ -38,9 +38,9 @@ struct dirl_templ { - const char* header; - const char* entry; - const char* footer; + char* header; + char* entry; + char* footer; }; struct dirl_templ diff --git a/util.c b/util.c index e59aaa8..c998d8c 100644 --- a/util.c +++ b/util.c @@ -20,162 +20,162 @@ char *argv0; static void verr(const char *fmt, va_list ap) { - if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) { - fprintf(stderr, "%s: ", argv0); - } + if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) { + fprintf(stderr, "%s: ", argv0); + } - vfprintf(stderr, fmt, ap); + vfprintf(stderr, fmt, ap); - if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } + if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { + fputc(' ', stderr); + perror(NULL); + } else { + fputc('\n', stderr); + } } void warn(const char *fmt, ...) { - va_list ap; + va_list ap; - va_start(ap, fmt); - verr(fmt, ap); - va_end(ap); + va_start(ap, fmt); + verr(fmt, ap); + va_end(ap); } void die(const char *fmt, ...) { - va_list ap; + va_list ap; - va_start(ap, fmt); - verr(fmt, ap); - va_end(ap); + va_start(ap, fmt); + verr(fmt, ap); + va_end(ap); - exit(1); + exit(1); } void epledge(const char *promises, const char *execpromises) { - (void)promises; - (void)execpromises; + (void)promises; + (void)execpromises; #ifdef __OpenBSD__ - if (pledge(promises, execpromises) == -1) { - die("pledge:"); - } + if (pledge(promises, execpromises) == -1) { + die("pledge:"); + } #endif /* __OpenBSD__ */ } void eunveil(const char *path, const char *permissions) { - (void)path; - (void)permissions; + (void)path; + (void)permissions; #ifdef __OpenBSD__ - if (unveil(path, permissions) == -1) { - die("unveil:"); - } + if (unveil(path, permissions) == -1) { + die("unveil:"); + } #endif /* __OpenBSD__ */ } int timestamp(char *buf, size_t len, time_t t) { - struct tm tm; + struct tm tm; - if (gmtime_r(&t, &tm) == NULL || - strftime(buf, len, "%a, %d %b %Y %T GMT", &tm) == 0) { - return 1; - } + if (gmtime_r(&t, &tm) == NULL || + strftime(buf, len, "%a, %d %b %Y %T GMT", &tm) == 0) { + return 1; + } - return 0; + return 0; } int esnprintf(char *str, size_t size, const char *fmt, ...) { - va_list ap; - int ret; + va_list ap; + int ret; - va_start(ap, fmt); - ret = vsnprintf(str, size, fmt, ap); - va_end(ap); + va_start(ap, fmt); + ret = vsnprintf(str, size, fmt, ap); + va_end(ap); - return (ret < 0 || (size_t)ret >= size); + return (ret < 0 || (size_t)ret >= size); } int 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) { - return 1; - } + if (len + prefixlen + 1 > size) { + return 1; + } - memmove(str + prefixlen, str, len + 1); - memcpy(str, prefix, prefixlen); + memmove(str + prefixlen, str, len + 1); + memcpy(str, prefix, prefixlen); - return 0; + return 0; } void html_escape(const char *src, char *dst, size_t dst_siz) { - const struct { - char c; - char *s; - } escape[] = { - { '&', "&" }, - { '<', "<" }, - { '>', ">" }, - { '"', """ }, - { '\'', "'" }, - }; - size_t i, j, k, esclen; + const struct { + char c; + char *s; + } escape[] = { + { '&', "&" }, + { '<', "<" }, + { '>', ">" }, + { '"', """ }, + { '\'', "'" }, + }; + size_t i, j, k, esclen; - for (i = 0, j = 0; src[i] != '\0'; i++) { - for (k = 0; k < LEN(escape); k++) { - if (src[i] == escape[k].c) { - break; - } - } - if (k == LEN(escape)) { - /* no escape char at src[i] */ - if (j == dst_siz - 1) { - /* silent truncation */ - break; - } else { - dst[j++] = src[i]; - } - } else { - /* escape char at src[i] */ - esclen = strlen(escape[k].s); + for (i = 0, j = 0; src[i] != '\0'; i++) { + for (k = 0; k < LEN(escape); k++) { + if (src[i] == escape[k].c) { + break; + } + } + if (k == LEN(escape)) { + /* no escape char at src[i] */ + if (j == dst_siz - 1) { + /* silent truncation */ + break; + } else { + dst[j++] = src[i]; + } + } else { + /* escape char at src[i] */ + esclen = strlen(escape[k].s); - if (j >= dst_siz - esclen) { - /* silent truncation */ - break; - } else { - memcpy(&dst[j], escape[k].s, esclen); - j += esclen; - } - } - } - dst[j] = '\0'; + if (j >= dst_siz - esclen) { + /* silent truncation */ + break; + } else { + memcpy(&dst[j], escape[k].s, esclen); + j += esclen; + } + } + } + dst[j] = '\0'; } -char* -replace(const char *src, const char *old, const char* new) { +void +replace(char **src, const char *old, const char* new) { int old_len = strlen(old); int new_len = strlen(new); - int src_len = strlen(src); + int src_len = strlen(*src); /* Count needed replacements */ - const char* tmp = src; + const char* tmp = *src; int replc=0; while ((tmp=strstr(tmp, old))) { 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); /* Now start replacing */ - const char *srcidx = src; - const char *srcidx_old = src; + const char *srcidx = *src; + const char *srcidx_old = *src; char *bufidx = buf; while (replc--) { @@ -202,7 +202,56 @@ replace(const char *src, const char *old, const char* new) { 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 @@ -213,39 +262,39 @@ long long strtonum(const char *numstr, long long minval, long long maxval, const char **errstrp) { - long long ll = 0; - int error = 0; - char *ep; - struct errval { - const char *errstr; - int err; - } ev[4] = { - { NULL, 0 }, - { "invalid", EINVAL }, - { "too small", ERANGE }, - { "too large", ERANGE }, - }; + long long ll = 0; + int error = 0; + char *ep; + struct errval { + const char *errstr; + int err; + } ev[4] = { + { NULL, 0 }, + { "invalid", EINVAL }, + { "too small", ERANGE }, + { "too large", ERANGE }, + }; - ev[0].err = errno; - errno = 0; - if (minval > maxval) { - error = INVALID; - } else { - ll = strtoll(numstr, &ep, 10); - if (numstr == ep || *ep != '\0') - error = INVALID; - else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) - error = TOOSMALL; - else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) - error = TOOLARGE; - } - if (errstrp != NULL) - *errstrp = ev[error].errstr; - errno = ev[error].err; - if (error) - ll = 0; + ev[0].err = errno; + errno = 0; + if (minval > maxval) { + error = INVALID; + } else { + ll = strtoll(numstr, &ep, 10); + if (numstr == ep || *ep != '\0') + error = INVALID; + else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) + error = TOOSMALL; + else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) + error = TOOLARGE; + } + if (errstrp != NULL) + *errstrp = ev[error].errstr; + errno = ev[error].err; + if (error) + ll = 0; - return ll; + return ll; } /* @@ -257,10 +306,10 @@ strtonum(const char *numstr, long long minval, long long maxval, void * reallocarray(void *optr, size_t nmemb, size_t size) { - if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && - nmemb > 0 && SIZE_MAX / nmemb < size) { - errno = ENOMEM; - return NULL; - } - return realloc(optr, size * nmemb); + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); } diff --git a/util.h b/util.h index 70179ac..c595ace 100644 --- a/util.h +++ b/util.h @@ -53,7 +53,8 @@ int timestamp(char *, size_t, time_t); int esnprintf(char *, size_t, const char *, ...); int prepend(char *, size_t, const char *); 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); long long strtonum(const char *, long long, long long, const char **);