summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAaron Ball <nullspoon@oper.io>2020-12-28 22:10:32 -0700
committerAaron Ball <nullspoon@oper.io>2020-12-29 21:28:22 -0700
commitc407d6fa52aa5e579dd7e42e0b161111a8e31032 (patch)
tree532401f86c88a6fdca4f4ea0f102bdecb9f8fd56 /src
parent1e223470ee80c794f2330e5a80145fd5a0dfb504 (diff)
downloadoper.io-c407d6fa52aa5e579dd7e42e0b161111a8e31032.tar.gz
oper.io-c407d6fa52aa5e579dd7e42e0b161111a8e31032.tar.xz
j2:Add support for inline shell directiveimplement-runsh
This allows for render-time shell command input to the output document. This also simplifies the j2_readvar function to make it handle input line by line rather than as a pure stream, character by character, which had incredibly complex logic and was very brittle. The new method is more durable, though is a bit less efficient due to reprocessing the string, though it no longer seeks back and forth. Add j2_strstr function and better protect against buffer overflow This also updates the librem 5 no wifi post to print the current date and time at pageload.
Diffstat (limited to 'src')
-rw-r--r--src/common.c20
-rw-r--r--src/common.h3
-rw-r--r--src/j2.c100
-rw-r--r--src/j2.h5
-rw-r--r--src/main.c2
5 files changed, 96 insertions, 34 deletions
diff --git a/src/common.c b/src/common.c
index 1891d78..db33bc0 100644
--- a/src/common.c
+++ b/src/common.c
@@ -75,3 +75,23 @@ int html_read_title(char* path, char* out) {
return -1;
}
+
+char* runsh(char* cmd) {
+ char buf[2048] = {'\0'};
+ char* out = malloc(1);
+ FILE* fd = NULL;
+ unsigned long len = 0;
+
+ fd = popen(cmd, "r");
+ while(fgets(buf, 2048, fd) != NULL) {
+ len += strlen(buf);
+ out = realloc(out, len + 1);
+ strcat(out, buf);
+ }
+ pclose(fd);
+
+ if(out[len - 1] == '\n')
+ out[len-1] = '\0';
+ return out;
+}
+
diff --git a/src/common.h b/src/common.h
index aca549d..03529dd 100644
--- a/src/common.h
+++ b/src/common.h
@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#ifndef _common_h
@@ -29,4 +30,6 @@ int file_exists(char*);
int html_read_title(char*, char*);
+char* runsh(char*);
+
#endif
diff --git a/src/j2.c b/src/j2.c
index 05fe442..b636c77 100644
--- a/src/j2.c
+++ b/src/j2.c
@@ -18,30 +18,47 @@
#include "j2.h"
-int j2_readvar(FILE* fd, char* buf) {
- char c;
- int i = 0;
- fpos_t startpos;
+char* j2_strstr(char* line) {
+ char* start;
+ char* end;
- fgetpos(fd, &startpos);
- //long seekstart = SEEK_CUR;
+ start = strstr(line, "{{ ");
+ if(start == NULL)
+ return NULL;
+ //start += 3; // Advance past the '{{ '
- if((c = fgetc(fd)) != '{') {
- fsetpos(fd, &startpos);
- return -1;
- }
- if(fgetc(fd) != ' ') {
- fsetpos(fd, &startpos);
- return -1;
- }
+ // Check for the var close to ensure a complete definition is present
+ end = strstr(start, " }}");
- while((c = fgetc(fd)) != ' ') {
- buf[i] = c;
- i++;
- }
+ // Incorrectly formatted, early return null
+ if(end == NULL)
+ return NULL;
+
+ return start;
+}
+
+
+char* j2_readvar(char* line, char* buf, int maxlen) {
+ char* start = NULL;
+ char* end = NULL;
- buf[i] = '\0';
- return 1;
+ start = j2_strstr(line);
+ if(start == NULL)
+ return NULL;
+ start += 3;
+
+ // Because of how j2_strstr works, this will always work if start is not null
+ end = strstr(start, " }}");
+
+ // Only copy up to maxlen to avoid buffer overflows
+ if(end - start > maxlen) {
+ strncpy(buf, start, maxlen);
+ buf[maxlen] = '\0';
+ } else {
+ strncpy(buf, start, end - start);
+ buf[end - start] = '\0';
+ }
+ return end + 3;
}
@@ -50,23 +67,42 @@ int j2_readvar(FILE* fd, char* buf) {
* matching environment variables.
*/
int j2_cat(char* path) {
- char buf[512] = {'\0'};
- char c;
+ char line[J2_MAXLINE] = {'\0'};
+ char buf[J2_MAXBUF] = {'\0'};
FILE* fd = fopen(path, "r");
+ char* value = NULL;
+ char* varstart = NULL;
+ char* varend = NULL;
- while((c = fgetc(fd)) != EOF) {
- if(c == '{') {
- if(j2_readvar(fd, buf) == -1) {
- printf("{%s", buf);
- continue;
- }
+ while(fgets(line, J2_MAXLINE, fd) != NULL) {
+ varstart = j2_strstr(line);
- printf("%s", getenv(buf));
- fgetc(fd);
- fgetc(fd);
+ if(!varstart) {
+ printf(line);
continue;
}
- printf("%c", c);
+ varend = j2_readvar(varstart, buf, J2_MAXBUF);
+
+ // Break the beginning of the string and the beginning of the variable
+ // (this overwrites the first { that opens the variable def)
+ *varstart = '\0';
+ // Because of the inserted null byte, this will print from byte 0 to there
+ printf("%s", line);
+
+ // Execute the variable directive and print the output
+ if(strncmp(buf, "shell ", 6) == 0) {
+ // Execute the provided shell command and print that
+ value = runsh(&buf[6]);
+ printf("%s", value);
+ free(value);
+ } else {
+ // Print the referenced environment variable
+ value = getenv(buf);
+ printf("%s", value);
+ }
+
+ // varend points to after the final }} of the variable def
+ printf("%s", varend);
}
fclose(fd);
diff --git a/src/j2.h b/src/j2.h
index 3e958d3..c08f9ec 100644
--- a/src/j2.h
+++ b/src/j2.h
@@ -18,9 +18,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "common.h"
-int j2_readvar(FILE*, char*);
+#define J2_MAXLINE 4096
+#define J2_MAXBUF 1024
+char* j2_readvar(char*, char*, int);
/**
* Reads a jinja file and cats the output, interpolating variables, values from
diff --git a/src/main.c b/src/main.c
index 0e608f6..297ea96 100644
--- a/src/main.c
+++ b/src/main.c
@@ -83,7 +83,7 @@ int main(int argc, char* argv[], char* envp[]) {
setenv("PAGE_TITLE", title, 1);
j2_cat(header);
- catfile(path);
+ j2_cat(path);
j2_cat(footer);
fflush(stdout);

Generated by cgit