slweb

Једноставни генератор статичких веб страна
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 0eefb4be3aff0c27b09cfc93d25d5f1b25fccfad
родитељ 3ab244557b38726b4c564976a9f919b900278297
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Thu, 28 Jan 2021 15:29:07 +0100

Switched from popen() -> execvp() + pipe() for more robust math mode; revised REALLOC and corrected a few bugs

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
Mdefs.h | 13++++++++++++-
Mindex.html | 2+-
Mslweb.c | 242+++++++++++++++++++++++++++++++++++++++++--------------------------------------
измењених датотека: 3, додавања: 140(+), брисања: 117(-)

diff --git a/defs.h b/defs.h @@ -29,6 +29,7 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> +#include <sys/prctl.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> @@ -38,16 +39,26 @@ #include <uniwidth.h> #define PROGRAMNAME "slweb" -#define VERSION "0.3.6" +#define VERSION "0.3.7" #define COPYRIGHTYEAR "2020, 2021" #define BUFSIZE 1024 #define KEYSIZE 256 +#define SMALL_ARGSIZE 256 #define DATEBUFSIZE 12 static const char timestamp_format[] = "d.m.y"; static const char timestamp_output_ext[] = ".html"; +static const char CMD_GIT_LOG[] = "xargs"; +static const char* CMD_GIT_LOG_ARGS[] + = { "xargs", "-I{}", "git", "log", "-1", + "--pretty=format:{} %h %ci (%cn) %d", NULL }; + +static const char CMD_KATEX[] = "katex"; +static const char* CMD_KATEX_INLINE_ARGS[] = { "katex", NULL }; +static const char* CMD_KATEX_DISPLAY_ARGS[] = { "katex", "-d", NULL }; + typedef enum { FALSE = 0, diff --git a/index.html b/index.html @@ -136,7 +136,7 @@ this program. If not, see &lt;<a href="https://www.gnu.org/licenses">https://www <div id="git-log"> Previous commit: -index.slw 788b45f 2021-01-25 12:46:17 +0100 (Страхиња Радић) (HEAD -> master, origin/master, origin/HEAD) +index.slw 3ab2445 2021-01-25 21:07:42 +0100 (Страхиња Радић) (HEAD -> master, origin/master, origin/HEAD) </div><!--git-log--> diff --git a/slweb.c b/slweb.c @@ -18,7 +18,6 @@ */ #include "defs.h" -#include <stdint.h> static size_t lineno = 0; static size_t colno = 1; @@ -54,23 +53,26 @@ static ULONG state = ST_NONE; #define CALLOC(ptr, ptrtype, nmemb) { ptr = calloc(nmemb, sizeof(ptrtype)); \ CHECKEXITNOMEM(ptr) } -#define REALLOC(ptr, newsize) { ptr = realloc(ptr, newsize); \ - CHECKEXITNOMEM(ptr) } +#define REALLOC(ptr, ptrtype, newsize) { ptrtype* newptr = realloc(ptr, newsize); \ + CHECKEXITNOMEM(newptr) \ + ptr = newptr; } #define REALLOCARRAY(ptr, membtype, newcount) { ptr = realloc(ptr, \ newcount * sizeof(membtype)); CHECKEXITNOMEM(ptr) } #define CHECKCOPY(token, ptoken, token_size, pline) { \ - if (ptoken - token + 1 > token_size) \ + if (ptoken + 2 > token + token_size) \ { \ + size_t old_size = token_size; \ token_size += BUFSIZE; \ - REALLOC(token, token_size) \ + REALLOC(token, uint8_t, token_size) \ + ptoken = token + old_size - 1; \ } \ *ptoken++ = *pline++; } #define RESET_TOKEN(token, ptoken, token_size) { \ token_size = BUFSIZE; \ - REALLOC(token, token_size) \ + REALLOC(token, uint8_t, token_size) \ *token = 0; ptoken = token; } int @@ -181,10 +183,10 @@ set_basedir(char* arg, char** basedir, size_t* basedir_size) if (arg_len < 1) exit(error(1, (uint8_t*)"--basedir: Argument required")); - if (arg_len > *basedir_size) + if (arg_len + 1 > *basedir_size) { *basedir_size = arg_len+1; - REALLOC(*basedir, *basedir_size) + REALLOC(*basedir, char, *basedir_size) } strncpy(*basedir, arg, *basedir_size-1); *(*basedir + arg_len) = 0; @@ -240,7 +242,7 @@ print_output(FILE* output, char* fmt, ...) if (u8_strlen(csv_template) + buf_len > csv_template_size) { csv_template_size += BUFSIZE; - REALLOC(csv_template, csv_template_size) + REALLOC(csv_template, uint8_t, csv_template_size) } u8_strncat(csv_template, buf, csv_template_size - u8_strlen(csv_template) - 1); @@ -252,19 +254,61 @@ print_output(FILE* output, char* fmt, ...) return 0; } +#define PIPE_READ_INDEX 0 +#define PIPE_WRITE_INDEX 1 + int -print_command(uint8_t* command, FILE* output, BOOL strip_newlines) +print_command(const char* command, + const uint8_t* pass_arguments[], const uint8_t* pipe_arguments[], + FILE* output, BOOL strip_newlines) { - if (!command) + if (!command || !pass_arguments) exit(error(EINVAL, (uint8_t*)"print_command: Invalid argument")); - FILE* cmd_output = popen((char*)command, "r"); + pid_t pid = 0; + int arg_pipe_fds[2]; + int output_pipe_fds[2]; + int pstatus = 0; + + pipe(arg_pipe_fds); + pipe(output_pipe_fds); + pid = fork(); + if (pid == 0) + { + close(arg_pipe_fds[PIPE_WRITE_INDEX]); + close(output_pipe_fds[PIPE_READ_INDEX]); + + prctl(PR_SET_PDEATHSIG, SIGTERM); + + dup2(arg_pipe_fds[PIPE_READ_INDEX], STDIN_FILENO); + dup2(output_pipe_fds[PIPE_WRITE_INDEX], STDOUT_FILENO); + dup2(output_pipe_fds[PIPE_WRITE_INDEX], STDERR_FILENO); - if (!cmd_output) + execvp(command, (char* const*)pass_arguments); + exit(1); + } + else if (pid < 0) + exit(error(errno, (uint8_t*)"Fork failed")); + + /* Parent */ + close(arg_pipe_fds[PIPE_READ_INDEX]); + close(output_pipe_fds[PIPE_WRITE_INDEX]); + FILE* cmd_input = fdopen(arg_pipe_fds[PIPE_WRITE_INDEX], "w"); + FILE* cmd_output = fdopen(output_pipe_fds[PIPE_READ_INDEX], "r"); + + if (!cmd_input || !cmd_output) + exit(error(1, (uint8_t*)"Cannot fdopen")); + + if (pipe_arguments) { - perror("popen"); - return 1; + const uint8_t** ppipe_argument = pipe_arguments; + while (ppipe_argument && *ppipe_argument) + { + fprintf(cmd_input, "%s\n", *ppipe_argument); + ppipe_argument++; + } } + fclose(cmd_input); uint8_t* cmd_output_line = NULL; CALLOC(cmd_output_line, uint8_t, BUFSIZE) @@ -281,7 +325,18 @@ print_command(uint8_t* command, FILE* output, BOOL strip_newlines) strip_newlines ? "" : "\n"); } free(cmd_output_line); - return pclose(cmd_output); + + fclose(cmd_output); + + kill(pid, SIGKILL); + pid_t wpid = waitpid(pid, &pstatus, 0); + if (wpid < 0) + warning(pstatus, (uint8_t*)"Child returned nonzero status, errno = %d", + errno); + if (WIFEXITED(pstatus)) + return WEXITSTATUS(pstatus); + + return wpid; } int @@ -353,26 +408,27 @@ process_git_log(FILE* output) size_t basename_size = strlen(input_filename)+1; CALLOC(basename, char, basename_size) char* slash = strrchr(input_filename, '/'); + pid_t result = 0; + if (slash) strncpy(basename, slash+1, basename_size-1); else strncpy(basename, input_filename, basename_size-1); + uint8_t* pipe_args[] = { (uint8_t*)basename, NULL }; + print_output(output, "<div id=\"git-log\">\nPrevious commit:\n"); - uint8_t* command = NULL; - CALLOC(command, uint8_t, BUFSIZE) - u8_snprintf(command, BUFSIZE-1, - "git log -1 --pretty=format:\"%s %%h %%ci (%%cn) %%d\"" - " || echo \"(Not in a Git repository)\"", - basename); - if (print_command(command, output, FALSE)) + result = print_command(CMD_GIT_LOG, + (const uint8_t**)CMD_GIT_LOG_ARGS, + (const uint8_t**)pipe_args, output, FALSE); + + if (result) { print_output(output, "</div><!--git-log-->\n"); - return warning(1, (uint8_t*)"git-log: Cannot run git"); + return warning(result, (uint8_t*)"git-log: Cannot run git"); } print_output(output, "</div><!--git-log-->\n"); - free(command); free(basename); return 0; @@ -1090,7 +1146,7 @@ process_macro(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links, if (macros_count > 1) { - REALLOC(macros, macros_count * sizeof(KeyValue)) + REALLOC(macros, KeyValue, macros_count * sizeof(KeyValue)) pmacros = macros + macros_count - 1; } CALLOC(pmacros->key, uint8_t, KEYSIZE) @@ -1336,12 +1392,10 @@ process_image(uint8_t* image_text, uint8_t* image_id, FILE* output, BOOL add_lin int process_line_start(uint8_t* line, BOOL first_line_in_doc, - BOOL previous_line_blank, BOOL processed_start_of_line, - BOOL read_yaml_macros_and_links, BOOL list_para, - FILE* output, uint8_t** token, uint8_t** ptoken) + BOOL previous_line_blank, BOOL read_yaml_macros_and_links, + BOOL list_para, FILE* output, uint8_t** token, uint8_t** ptoken) { if ((first_line_in_doc || previous_line_blank) - && !processed_start_of_line && !(state & (ST_BLOCKQUOTE | ST_PRE))) { if (!list_para) @@ -1381,7 +1435,7 @@ process_inline_footnote(uint8_t* token, BOOL read_yaml_macros_and_links, if (inline_footnote_count == 1 && footnote_count > 0) warning(1, (u_int8_t*)"Both inline and regular footnotes present"); else if (inline_footnote_count > 1) - REALLOC(inline_footnotes, sizeof(uint8_t*) * inline_footnote_count) + REALLOC(inline_footnotes, uint8_t*, sizeof(uint8_t*) * inline_footnote_count) CALLOC(inline_footnotes[inline_footnote_count-1], uint8_t, token_len+1) u8_strncpy(inline_footnotes[inline_footnote_count-1], token, token_len); @@ -1409,7 +1463,7 @@ process_footnote(uint8_t* token, BOOL footnote_definition, BOOL footnote_output, warning(1, (u_int8_t*)"Both inline and regular footnotes present"); else if (footnote_count > 1) { - REALLOC(footnotes, footnote_count * sizeof(KeyValue)) + REALLOC(footnotes, KeyValue, footnote_count * sizeof(KeyValue)) pfootnotes = footnotes + footnote_count - 1; } CALLOC(pfootnotes->key, uint8_t, KEYSIZE) @@ -1448,10 +1502,9 @@ process_text_token(uint8_t* line, BOOL first_line_in_doc, { if (!(state & ST_YAML)) { - if (add_enclosing_paragraph) + if (add_enclosing_paragraph && !processed_start_of_line) process_line_start(line, first_line_in_doc, previous_line_blank, - processed_start_of_line, read_yaml_macros_and_links, - list_para, output, token, ptoken); + read_yaml_macros_and_links, list_para, output, token, ptoken); **ptoken = 0; if (**token && !read_yaml_macros_and_links && !(state & ST_MACRO_BODY)) @@ -1462,71 +1515,23 @@ process_text_token(uint8_t* line, BOOL first_line_in_doc, } int -process_formula(FILE* output, uint8_t* token, BOOL display_formula) +process_formula(FILE* output, const uint8_t* token, BOOL display_formula) { - uint8_t* command = NULL; - uint8_t* new_token = NULL; - uint8_t* pnew_token = NULL; - uint8_t* ptoken = NULL; - size_t new_token_size = 0; - int result = 0; - - CALLOC(command, uint8_t, BUFSIZE) - new_token_size = BUFSIZE; - CALLOC(new_token, uint8_t, new_token_size) - ptoken = token; - pnew_token = new_token; - - while (ptoken && *ptoken) - { - switch (*ptoken) - { - case '\\': - if (ptoken - token + 2 > new_token_size) - { - new_token_size += BUFSIZE; - REALLOC(new_token, new_token_size) - } - *pnew_token++ = '\\'; - *pnew_token++ = *ptoken++; - break; - - case '%': - ptoken++; - break; - - case '"': - if (ptoken - token + 2 > new_token_size) - { - new_token_size += BUFSIZE; - REALLOC(new_token, new_token_size) - } - *pnew_token = 0; - u8_strncat(pnew_token, (uint8_t*)"\\", - new_token_size-u8_strlen(new_token)-1); - pnew_token++; - *pnew_token++ = *ptoken++; - break; - default: - *pnew_token++ = *ptoken++; - } - } + int result = 0; + const uint8_t* pipe_args[] = { token, NULL}; - *pnew_token = 0; + result = print_command(CMD_KATEX, + display_formula + ? (const uint8_t**)CMD_KATEX_DISPLAY_ARGS + : (const uint8_t**)CMD_KATEX_INLINE_ARGS, + (const uint8_t**)pipe_args, output, TRUE); - snprintf((char*)command, BUFSIZE-1, "katex %s<<<\"%s\"", - display_formula ? "-d " : "", - new_token); - - result = print_command(command, output, TRUE); if (result) print_output(output, "%s$%s$%s", display_formula ? "$" : "", token, display_formula ? "$" : ""); - free(new_token); - free(command); return result; } @@ -1657,7 +1662,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, BOOL first_line_in_doc = TRUE; BOOL skip_change_first_line_in_doc = FALSE; BOOL skip_eol = FALSE; - BOOL reset_token = TRUE; + BOOL keep_token = FALSE; BOOL previous_line_blank = FALSE; BOOL processed_start_of_line = FALSE; BOOL add_image_links = TRUE; @@ -1782,7 +1787,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, { skip_eol = TRUE; - if (yaml_parsed) + if (yaml_parsed && !read_yaml_macros_and_links) { process_horizontal_rule(output); pline = NULL; @@ -2070,9 +2075,8 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, && pline_len > 1 && *(pline+1) == '[') { process_line_start(line, first_line_in_doc, - previous_line_blank, processed_start_of_line, - read_yaml_macros_and_links, list_para, output, - &token, &ptoken); + previous_line_blank, read_yaml_macros_and_links, + list_para, output, &token, &ptoken); /* Ignore abbreviations (for now) */ pline = NULL; @@ -2081,7 +2085,8 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, && pline_len > 2 && startswith((char*)pline, "***")) { skip_eol = TRUE; - process_horizontal_rule(output); + if (!read_yaml_macros_and_links) + process_horizontal_rule(output); pline = NULL; } else if (pline_len > 1 && *(pline+1) == '*') @@ -2253,7 +2258,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (pmacros->value_size < value_len + token_len + 1) { pmacros->value_size += token_len; - REALLOC(pmacros->value, pmacros->value_size) + REALLOC(pmacros->value, uint8_t, pmacros->value_size) } u8_strncat(pmacros->value, token, pmacros->value_size-1); } @@ -2726,7 +2731,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (token_len + 1 > link_size) { link_size = token_len+1; - REALLOC(link_text, link_size) + REALLOC(link_text, uint8_t, link_size) } } else @@ -2751,6 +2756,11 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, break; } } + else + { + CHECKCOPY(token, ptoken, token_size, pline) + colno++; + } break; case '^': @@ -2834,13 +2844,13 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, read_yaml_macros_and_links, list_para, output, &token, &ptoken, &token_size, TRUE); - processed_start_of_line = TRUE; } + processed_start_of_line = TRUE; state ^= ST_DISPLAY_FORMULA; if (state & ST_DISPLAY_FORMULA) - reset_token = FALSE; + keep_token = TRUE; else { *ptoken = 0; @@ -2848,8 +2858,8 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (!read_yaml_macros_and_links) process_formula(output, token, TRUE); + keep_token = FALSE; RESET_TOKEN(token, ptoken, token_size) - reset_token = TRUE; } pline += 2; @@ -2870,13 +2880,13 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, read_yaml_macros_and_links, list_para, output, &token, &ptoken, &token_size, TRUE); - processed_start_of_line = TRUE; } + processed_start_of_line = TRUE; state ^= ST_FORMULA; if (state & ST_FORMULA) - reset_token = FALSE; + keep_token = TRUE; else { *ptoken = 0; @@ -2884,8 +2894,8 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (!read_yaml_macros_and_links) process_formula(output, token, FALSE); + keep_token = FALSE; RESET_TOKEN(token, ptoken, token_size) - reset_token = TRUE; } pline++; @@ -2913,10 +2923,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, { size_t token_len = u8_strlen(token); - if (ptoken - token + 1 > token_size) + if (ptoken + 2 > token + token_size) { + size_t old_size = token_size; token_size += BUFSIZE; - REALLOC(token, token_size) + REALLOC(token, uint8_t, token_size) + ptoken = token + old_size - 1; } u8_strncat(token, (uint8_t*)" ", token_size - token_len - 1); @@ -2938,10 +2950,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, { size_t value_len = u8_strlen(pmacros->value); - if (sizeof(pmacros->value) < value_len + token_len + 1) + if (pmacros->value_size < value_len + token_len + 1) { pmacros->value_size += BUFSIZE; - REALLOC(pmacros->value, pmacros->value_size) + REALLOC(pmacros->value, uint8_t, pmacros->value_size) } u8_strncat(pmacros->value, token, pmacros->value_size-value_len-1); @@ -2967,10 +2979,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, { size_t value_len = u8_strlen(pfootnotes->value); - if (sizeof(pfootnotes->value) < value_len + token_len + 1) + if (pfootnotes->value_size < value_len + token_len + 1) { pfootnotes->value_size += BUFSIZE; - REALLOC(pfootnotes->value, pfootnotes->value_size) + REALLOC(pfootnotes->value, uint8_t, pfootnotes->value_size) } u8_strncat(pfootnotes->value, token, pfootnotes->value_size-value_len-1); @@ -3005,7 +3017,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, RESET_TOKEN(token, ptoken, token_size) heading_level = 0; } - else + else if (!(state & (ST_DISPLAY_FORMULA | ST_FORMULA))) process_text_token(line, first_line_in_doc, previous_line_blank, processed_start_of_line, @@ -3055,7 +3067,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (pmacros->value_size < value_len + token_len + 1) { pmacros->value_size += token_len; - REALLOC(pmacros->value, pmacros->value_size) + REALLOC(pmacros->value, uint8_t, pmacros->value_size) } u8_strncat(pmacros->value, token, pmacros->value_size-1); } @@ -3084,7 +3096,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, | ST_LINK_SECOND_ARG))) print_output(output, "\n"); - if (reset_token) + if (!keep_token) RESET_TOKEN(token, ptoken, token_size) if (!skip_change_first_line_in_doc @@ -3237,7 +3249,7 @@ main(int argc, char** argv) if (buffer_len + bufline_len + 1 > buffer_size) { buffer_size += BUFSIZE; - REALLOC(buffer, buffer_size) + REALLOC(buffer, uint8_t, buffer_size) } u8_strncat(buffer, bufline, buffer_size-buffer_len-1); buffer_len += bufline_len;