/** * This CGI program renders the oper.io blog * Copyright (C) 2024 Aaron Ball * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "j2.h" char* j2_strstr(char* line) { char* start; char* end; start = strstr(line, "{{ "); if(start == NULL) return NULL; //start += 3; // Advance past the '{{ ' // Check for the var close to ensure a complete definition is present end = strstr(start, " }}"); // 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; 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; } /** * Reads a jinja file and cats the output, interpolating variables, values from * matching environment variables. */ int j2_cat(char* path) { 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(fgets(line, J2_MAXLINE, fd) != NULL) { varstart = j2_strstr(line); if(!varstart) { fputs(line, stdout); continue; } 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 fputs(line, stdout); // 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]); fputs(value, stdout); 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); return 0; }