Regex works now
added branding in a seperate file and a config.h replace_rules count in branding does not work as of now way better replace functions that actually work
This commit is contained in:
parent
f4f877148c
commit
62c15ab976
|
|
@ -10,7 +10,8 @@ bin/*
|
|||
|
||||
# Ignore temp editor files
|
||||
*.swp
|
||||
*.tmp
|
||||
|
||||
.vscode
|
||||
.vscode/*
|
||||
|
||||
!.gitkeep
|
||||
|
|
@ -3,8 +3,7 @@
|
|||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/include"
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/bin/gcc",
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb) Attach",
|
||||
"type": "cppdbg",
|
||||
"request": "attach",
|
||||
"program": "${workspaceFolder}/bin/cterm",
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Set Disassembly Flavor to Intel",
|
||||
"text": "-gdb-set disassembly-flavor intel",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "colorwrap",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/bin/cterm",
|
||||
"args": ["/bin/sh"],
|
||||
"cwd": "${workspaceFolder}/"
|
||||
}]
|
||||
}
|
||||
|
|
@ -1,20 +1,5 @@
|
|||
{
|
||||
"tasks": [
|
||||
{
|
||||
"type": "cppbuild",
|
||||
"label": "Make Build",
|
||||
"command": "make",
|
||||
"args": [
|
||||
"--directory=${workspaceFolder}"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "cppbuild",
|
||||
"label": "C/C++: gcc build active file",
|
||||
|
|
@ -34,7 +19,7 @@
|
|||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": false
|
||||
"isDefault": true
|
||||
},
|
||||
"detail": "Task generated by Debugger."
|
||||
}
|
||||
|
|
|
|||
9
Makefile
9
Makefile
|
|
@ -10,7 +10,10 @@ CFLAGS := -lreadline
|
|||
LIB := -L lib -lutil -lreadline
|
||||
INC := -I include
|
||||
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
@echo " Incrementing Build #"; make/genbuildno.sh
|
||||
@echo "Build number: $(shell grep BUILD include/config.h | cut -d' ' -f 3)"
|
||||
@echo " Linking..."
|
||||
@echo " $(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB) -O3
|
||||
@echo " Done!"
|
||||
|
|
@ -23,9 +26,11 @@ $(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
|
|||
clean:
|
||||
@echo " Cleaning...";
|
||||
@echo " cat /dev/null > $(TESTDIR)/trace.lp"; cat /dev/null > $(TESTDIR)/trace.lp;
|
||||
@echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
|
||||
@echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR)/* $(TARGET);
|
||||
|
||||
debug: CFLAGS += -ggdb -O0 -Wall -Wextra -pedantic -D"DEBUG=1"
|
||||
#debug: clean
|
||||
debug: CFLAGS += -ggdb -O0 -Wall -Wextra -pedantic -Wno-unused-variable -Wno-unused-parameter
|
||||
debug: CFLAGS += -D"DEBUG=1" -DGITBRANCH=\"$(shell git branch --show-current)\"
|
||||
debug: $(TARGET)
|
||||
|
||||
test:
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef _BRANDING_H
|
||||
#define _BRANDING_H
|
||||
|
||||
#if !defined(GITBRANCH)
|
||||
#define GITBRANCH ""
|
||||
#endif
|
||||
|
||||
void printbranding();
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
// Project global information
|
||||
#define PROJECT_NAME "cterm"
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_HOTFIX 0
|
||||
#define VERSION_BUILD 350
|
||||
|
||||
//#define DEFAULT_CMD "/bin/sh"
|
||||
#define CONF_DO_CMD_ACK 1
|
||||
|
||||
#define DEBG_DO_EOL_MARK 1
|
||||
//EOLMARK defined in parsebuffer()
|
||||
|
||||
|
||||
// Color codes
|
||||
#define KNRM "\x1B[0m"
|
||||
#define KRED "\x1B[31m"
|
||||
#define KGRN "\x1B[32m"
|
||||
#define KYEL "\x1B[33m"
|
||||
#define KBLU "\x1B[34m"
|
||||
#define KMAG "\x1B[35m"
|
||||
#define KCYN "\x1B[36m"
|
||||
#define KWHT "\x1B[37m"
|
||||
#define BKRED "\x1B[41m"
|
||||
#define BKGRN "\x1B[42m"
|
||||
#define BKYEL "\x1B[43m"
|
||||
#define BKBLU "\x1B[44m"
|
||||
#define BKMAG "\x1B[45m"
|
||||
#define BKCYN "\x1B[46m"
|
||||
#define BKWHT "\x1B[47m"
|
||||
|
||||
//child stdout read buffer size
|
||||
#define BUFCHUNKSIZE 4096
|
||||
#define BUFSAFEPAD 8 //shut it, ik its useless
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,8 +1,17 @@
|
|||
#ifndef _DEBUG_H
|
||||
#define _DEBUG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#if defined(DEBUG) && DEBUG > 0
|
||||
#define DEBUG_PRINT(fmt, ...) fprintf(stderr, "DEBUG: %s:%d:%s(): " fmt, \
|
||||
#define _DEBUG_H_DRED "\x1B[31m"
|
||||
#define _DEBUG_H_DNRM "\x1B[0m"
|
||||
#define DEBUG_PRINT(fmt, ...) fprintf(stderr, "[-] %s:%d:%s(): " fmt, \
|
||||
__FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
#define DDEBUG_PRINT(fmt, ...) fprintf(stderr, "[_] %s:%d:%s(): " fmt, \
|
||||
__FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
#define DEBUG_ERROR(fmt, ...) fprintf(stderr, "\n"_DEBUG_H_DRED"[!]"_DEBUG_H_DNRM" %s:%d:%s(): E.%d " fmt, \
|
||||
__FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
#define COLORTEST() fprintf(stderr, "Color Palate:\n" \
|
||||
KRED"KRED"KGRN"KGRN"KYEL"KYEL"KBLU"KBLU"KMAG"KMAG"KCYN"KCYN"KWHT"KWHT"KNRM"\n" \
|
||||
|
|
@ -11,7 +20,10 @@
|
|||
BKRED"KRED"BKGRN"KGRN"BKYEL"KYEL"BKBLU"KBLU"BKMAG"KMAG"BKCYN"KCYN"BKWHT"KWHT"KNRM"\n" )
|
||||
#else
|
||||
#define DEBUG_PRINT(fmt, args...) /* Don't do anything in release builds */
|
||||
#define DDEBUG_PRINT(fmt, args...)
|
||||
#define DEBUG_ERROR(fmt, args...)
|
||||
#define COLORTEST()
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef _LINEWORK_H
|
||||
#define _LINEWORK_H
|
||||
|
||||
#include <structdef.h>
|
||||
#include <regex.h>
|
||||
|
||||
|
||||
int line_regex_replace(ct_line *line, regex_t *regex, int replace_group, char *with, int max_instances);
|
||||
|
||||
int line_regex_wrap_match(ct_line *line, regex_t *regex, int target_capture_group, char *left, char *right, int max_instances);
|
||||
|
||||
#endif
|
||||
|
|
@ -4,5 +4,7 @@
|
|||
// You must free the result if result is non-NULL.
|
||||
char *str_replace(char *orig, char *rep, char *with);
|
||||
|
||||
//char *str_index_replace(char *orig, int rep_s, int rep_e, char *with);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,16 @@
|
|||
#ifndef _STRUCTDEF_H
|
||||
#define _STRUCTDEF_H
|
||||
|
||||
typedef struct {
|
||||
char* match_regex;
|
||||
int match_cflags;
|
||||
int replace_group; //if no regex groups (()), should be 0
|
||||
char* replace_with;
|
||||
} ct_match;
|
||||
|
||||
typedef struct {
|
||||
char* line_str; //pointer to first char in string
|
||||
int need_free; //tracks if buffer is on the stack or in heap
|
||||
} ct_line;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
sed -i "s/BUILD .*/BUILD $(($(grep BUILD include/config.h | cut -d' ' -f3) + 1 ))/g" include/config.h
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#include <branding.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <config.h>
|
||||
#include <debug.h>
|
||||
|
||||
// c macros to clean up lines later
|
||||
#define b_lenofarr(axx) (sizeof(axx)/sizeof(axx[0]))
|
||||
#define b_roundup(x) ((x)+1) & ~1
|
||||
|
||||
void printbranding(){
|
||||
//compile change config
|
||||
int min_content_padding = 4;
|
||||
char *box_pad_char = "----------"; // this is repeated to be in the horrror later; printf ugh;
|
||||
int box_top_width = 3; // --- text ---
|
||||
int box_side_width = 2; // -- text --
|
||||
|
||||
|
||||
char pre_print_lines[10][100] = {0}; //these are not end-user affectable so 100 chars should be fine for now.
|
||||
|
||||
sprintf(pre_print_lines[0], "%s v%d.%d.%d" , PROJECT_NAME, VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
|
||||
//sprintf(pre_print_lines[0], "%s v%d.%d.%d.%d" , PROJECT_NAME, VERSION_MAJOR, VERSION_MINOR, VERSION_HOTFIX, VERSION_BUILD);
|
||||
sprintf(pre_print_lines[1], "(c) never");
|
||||
sprintf(pre_print_lines[2], "%d rules loaded", 9); //TODO: actually use the number of rules loaded
|
||||
if (GITBRANCH) sprintf(pre_print_lines[3], "%s", GITBRANCH);
|
||||
|
||||
|
||||
|
||||
int max_used_line_length = 0;
|
||||
int used_lines = 0; //the number of lines actually used above
|
||||
for (int i = b_lenofarr(pre_print_lines)-1; i >= 0; i-- ){ //reverse loop from 9->0
|
||||
if (pre_print_lines[i][0] == 0) continue; //not set, dont care
|
||||
used_lines++;
|
||||
int line_length = strlen(pre_print_lines[i]);
|
||||
if (line_length > max_used_line_length) max_used_line_length = b_roundup(line_length);
|
||||
|
||||
if (line_length % 2 != 0) { //also going to use this (convienent) loop to pad the end of odd number length strings
|
||||
pre_print_lines[i][line_length]=' ';
|
||||
pre_print_lines[i][line_length+1]='\0'; //bad for user defined strings, but not in this case since its not
|
||||
}
|
||||
}
|
||||
//DDEBUG_PRINT("max_used_line_length=%d; used_lines=%d\n", max_used_line_length, used_lines);
|
||||
|
||||
int output_line_length = b_roundup(max_used_line_length+min_content_padding*2+box_top_width);
|
||||
//DDEBUG_PRINT("output_line_length=%d\n", output_line_length);
|
||||
|
||||
for (int i = 0; i<used_lines; i++){
|
||||
int box_pad = box_side_width;
|
||||
int content_len = strlen(pre_print_lines[i]);
|
||||
if (i == 0 || i == used_lines-1) box_pad = box_top_width;
|
||||
//DDEBUG_PRINT("box_pad=%d\n", box_pad);
|
||||
|
||||
int half_content_pad = ((output_line_length-content_len-box_pad)/2);
|
||||
//DDEBUG_PRINT("half_content_pad=%d\n", half_content_pad);
|
||||
printf("%.*s%*s%s%*s%.*s\n", box_pad, box_pad_char, half_content_pad, "", pre_print_lines[i], half_content_pad, "", box_pad, box_pad_char);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
#include <linework.h>
|
||||
#include <structdef.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
|
||||
|
||||
char *str_index_replace(const char *orig, const char *with, const int start_index, const int end_index){
|
||||
//no error checking on the args
|
||||
//will always call malloc
|
||||
char *result;
|
||||
char *tmp; //temporary pointer for replace process later
|
||||
int len_with = strlen(with); //doesnt change with loop repetitions
|
||||
int len_replace = end_index - start_index;
|
||||
int len_delta = len_with - len_replace; //how many chars are we changing the buffer by?
|
||||
|
||||
result = tmp = malloc(strlen(orig) + len_delta + 1);
|
||||
if (!result) return NULL;
|
||||
|
||||
int len_front = start_index;
|
||||
tmp = strncpy(tmp, orig, len_front) + len_front; //fill front end of buffer with already processed stuff
|
||||
tmp = strcpy(tmp, with) + len_with;
|
||||
strcpy(tmp, (orig + len_front + len_replace)); //writes the nice good \0 at the end
|
||||
/* reference: 0___1___2______4
|
||||
* fL...B
|
||||
* result: 0___1-----2_______4
|
||||
* fL.....B
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// @brief
|
||||
/// You could probably break this function if you really wanted to. fortunately, the regex is done at start time, not dynamically; yet :'(
|
||||
/// @param line mutates
|
||||
/// @param regex compiled regex
|
||||
/// @param target_capture_group int of the capture group to replace. 0=everything
|
||||
/// @param with
|
||||
/// @param max_instances 0=all instances
|
||||
/// @return 0 if no match; 1 if match and replace; -1 for error
|
||||
int line_regex_replace(ct_line *line, regex_t *regex, int target_capture_group, char *with, int max_instances){
|
||||
//TODO: logic for max_instances being 0
|
||||
|
||||
if (target_capture_group > (int)regex->re_nsub){
|
||||
DEBUG_ERROR("[target_capture_group bigger than number of subexpressions in regex]\n", 26);
|
||||
return -1;
|
||||
}
|
||||
//TODO: more failure conditions
|
||||
|
||||
/* References:
|
||||
* https://www.gnu.org/software/libc/manual/html_node/Matching-POSIX-Regexps.html
|
||||
* https://www.ibm.com/docs/en/i/7.2?topic=functions-regexec-execute-compiled-regular-expression
|
||||
*/
|
||||
int num_instances = 0;
|
||||
size_t nmatch = target_capture_group+1; //number of capture groups we care about
|
||||
regmatch_t pmatch[nmatch+1]; //0=everything, else is capture groups +1 for "safety"
|
||||
char *search_start_point = line->line_str;
|
||||
|
||||
int match_result = regexec(regex, search_start_point, nmatch, pmatch, 0);
|
||||
if (match_result==REG_NOMATCH) return 0;
|
||||
//DEBUG_PRINT("fresh:%s\n", line->line_str);
|
||||
|
||||
do {
|
||||
num_instances++;
|
||||
if (pmatch[target_capture_group].rm_so == -1) { DEBUG_ERROR("[Subexpression did not participate in an otherwise successful match]\n", 40); continue; }
|
||||
if (pmatch[target_capture_group].rm_eo < pmatch[target_capture_group].rm_so) { DEBUG_ERROR("[End offset < Start Offset] wtf???? now how did you manage that?\n", 41); continue; }
|
||||
|
||||
int front_delta = (search_start_point - line->line_str); //how far are we into the string?
|
||||
int start_index = pmatch[target_capture_group].rm_so + front_delta; //normalize indicies to be from real start
|
||||
int end_index = pmatch[target_capture_group].rm_eo + front_delta;
|
||||
//with
|
||||
|
||||
|
||||
//do the replace
|
||||
char *result = str_index_replace(line->line_str, with, start_index, end_index); //nice good pointer to the new and improved string
|
||||
if (!result) {
|
||||
DEBUG_ERROR("[replace error] idk\n", 85);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//clean up previous line memory and sub in the new pointer
|
||||
if(line->need_free) free(line->line_str);
|
||||
line->line_str = result;
|
||||
line->need_free = 1;
|
||||
|
||||
search_start_point = line->line_str + start_index + strlen(with); //its *back but recalculated for the new string
|
||||
//DEBUG_PRINT("new set:%s\n", line->line_str);
|
||||
//DEBUG_PRINT("new search space:%s\n", search_start_point);
|
||||
match_result = regexec(regex, search_start_point, nmatch, pmatch, REG_NOTBOL);
|
||||
} while(match_result==0 && num_instances<=max_instances);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int line_regex_wrap_match(ct_line *line, regex_t *regex, int target_capture_group, char *left, char *right, int max_instances){
|
||||
//TODO: logic for max_instances being 0
|
||||
if (target_capture_group > (int)regex->re_nsub){
|
||||
DEBUG_ERROR("[target_capture_group bigger than number of subexpressions in regex] MAYBE: fallback?\n", 26);
|
||||
return -1;
|
||||
}
|
||||
//TODO: more failure conditions
|
||||
|
||||
/* References:
|
||||
* https://www.gnu.org/software/libc/manual/html_node/Matching-POSIX-Regexps.html
|
||||
* https://www.ibm.com/docs/en/i/7.2?topic=functions-regexec-execute-compiled-regular-expression
|
||||
*/
|
||||
int num_instances = 0;
|
||||
size_t nmatch = target_capture_group+1; //number of capture groups we care about
|
||||
regmatch_t pmatch[nmatch+1]; //0=everything, else is capture groups +1 for "safety"
|
||||
char *search_start_point = line->line_str;
|
||||
|
||||
int match_result = regexec(regex, search_start_point, nmatch, pmatch, 0);
|
||||
if (match_result==REG_NOMATCH) return 0;
|
||||
|
||||
do {
|
||||
num_instances++;
|
||||
if (pmatch[target_capture_group].rm_so == -1) { DEBUG_ERROR("[Subexpression did not participate in an otherwise successful match]\n", 40); continue; }
|
||||
if (pmatch[target_capture_group].rm_eo < pmatch[target_capture_group].rm_so) { DEBUG_ERROR("[End offset < Start Offset] wtf???? now how did you manage that?\n", 41); continue; }
|
||||
|
||||
char *match_start = search_start_point + pmatch[target_capture_group].rm_so;
|
||||
int len_match = pmatch[target_capture_group].rm_eo - pmatch[target_capture_group].rm_so;
|
||||
int len_wrap = strlen(left) + strlen(right);
|
||||
char with[len_match + len_wrap + 1];
|
||||
strcpy(with, left);
|
||||
strncat(with, match_start, len_match);
|
||||
strcat(with, right);
|
||||
|
||||
int front_delta = (search_start_point - line->line_str); //how far are we into the string?
|
||||
int start_index = pmatch[target_capture_group].rm_so + front_delta; //normalize indicies to be from real start
|
||||
int end_index = pmatch[target_capture_group].rm_eo + front_delta;
|
||||
|
||||
//do the replace
|
||||
char *result = str_index_replace(line->line_str, with, start_index, end_index); //nice good pointer to the new and improved string
|
||||
if (!result) {
|
||||
DEBUG_ERROR("[replace error] idk\n", 85);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//clean up previous line memory and sub in the new pointer
|
||||
if(line->need_free) free(line->line_str);
|
||||
line->line_str = result;
|
||||
line->need_free = 1;
|
||||
|
||||
search_start_point = line->line_str + start_index + strlen(with); //its *back but recalculated for the new string
|
||||
//DEBUG_PRINT("new set:%s\n", line->line_str);
|
||||
//DEBUG_PRINT("new search space:%s\n", search_start_point);
|
||||
match_result = regexec(regex, search_start_point, nmatch, pmatch, REG_NOTBOL);
|
||||
} while(match_result==0 && num_instances<=max_instances);
|
||||
|
||||
return 1;
|
||||
}
|
||||
253
src/main.c
253
src/main.c
|
|
@ -10,158 +10,165 @@
|
|||
#include <fcntl.h>
|
||||
#include <readline/readline.h>
|
||||
//#include <readline/history.h>
|
||||
//regex branch init
|
||||
#include <regex.h>
|
||||
|
||||
|
||||
// Custom debug include for some debug macros and functions
|
||||
#include <config.h>
|
||||
#include <debug.h>
|
||||
#include <structdef.h>
|
||||
#include <branding.h>
|
||||
#include <linework.h>
|
||||
#include <notmine.h>
|
||||
|
||||
#define VERSIONSTRING "0.2"
|
||||
#define BUFCHUNKSIZE 4096
|
||||
#define BUFSAFEPAD 8
|
||||
#define KNRM "\x1B[0m"
|
||||
#define KRED "\x1B[31m"
|
||||
#define KGRN "\x1B[32m"
|
||||
#define KYEL "\x1B[33m"
|
||||
#define KBLU "\x1B[34m"
|
||||
#define KMAG "\x1B[35m"
|
||||
#define KCYN "\x1B[36m"
|
||||
#define KWHT "\x1B[37m"
|
||||
#define BKRED "\x1B[41m"
|
||||
#define BKGRN "\x1B[42m"
|
||||
#define BKYEL "\x1B[43m"
|
||||
#define BKBLU "\x1B[44m"
|
||||
#define BKMAG "\x1B[45m"
|
||||
#define BKCYN "\x1B[46m"
|
||||
#define BKWHT "\x1B[47m"
|
||||
|
||||
//temporary
|
||||
char *replace_rules[][2] = {
|
||||
{ "r--", KGRN"r--"KNRM },
|
||||
{ "rw-", KRED"rw-"KNRM },
|
||||
{ "alpine", KMAG"alpine"KNRM },
|
||||
{ " ..$", KBLU" .."KNRM"$" },
|
||||
{ " .$", KBLU" ."KNRM"$" },
|
||||
{ "^d", "^"KMAG"d"KNRM },
|
||||
{ "z9Da0Da1", KRED"z9Da0Da1"KNRM },
|
||||
ct_match replace_rules[]= {
|
||||
{ "alpine", 0, 0, KMAG"alpine"KNRM },
|
||||
{ "r--", 0, 0, KGRN"r--"KNRM },
|
||||
{ "rw-", 0, 0, KRED"rw-"KNRM },
|
||||
{ " ..$", 0, 0, KBLU" .."KNRM },
|
||||
{ " .$", 0, 0, KBLU" ."KNRM },
|
||||
{ "^d", 0, 0, KMAG"d"KNRM },
|
||||
{ "z9Da0Da1", 0, 0, KRED"z9Da0Da1"KNRM },
|
||||
};
|
||||
char ps1[] = KGRN"~>"KNRM;
|
||||
char ps1_ack[] = KBLU"1~"KNRM;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ct_line processline(ct_line current_line){
|
||||
|
||||
int rules_length = (sizeof(replace_rules)/sizeof(replace_rules[0]));
|
||||
|
||||
for (int i=0; i<rules_length; i++) {
|
||||
regex_t comp_regex;
|
||||
int match1_comp_result = regcomp(&comp_regex, replace_rules[i].match_regex, replace_rules[i].match_cflags); //unused but needed
|
||||
int regex_result = line_regex_replace(¤t_line, &comp_regex, replace_rules[i].replace_group, replace_rules[i].replace_with, 255);
|
||||
}
|
||||
|
||||
|
||||
return current_line;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void parsebuffer(char *roll_buffer, size_t read_length, int buffer_read_count) {
|
||||
#if !DEBG_DO_EOL_MARK
|
||||
char endstring[] = KNRM"\n";
|
||||
#else
|
||||
char endstring[] = KYEL"&"KNRM"\n";
|
||||
#endif
|
||||
|
||||
//dog garn dynamic memory allocation making me track it manually in a struct
|
||||
int line_number = 0; //true
|
||||
if (buffer_read_count != 0) line_number=1;
|
||||
|
||||
char *found_char = strtok(roll_buffer, "\r\n"); //basically replace "\r\n" with NULL
|
||||
while(found_char != NULL){
|
||||
ct_line current_line = {found_char, 0};
|
||||
ct_line post_processed_line = processline(current_line);
|
||||
|
||||
if (CONF_DO_CMD_ACK && line_number==0) write(STDOUT_FILENO, ps1_ack, strlen(ps1_ack));
|
||||
write(STDOUT_FILENO, post_processed_line.line_str, strlen(post_processed_line.line_str));
|
||||
write(STDOUT_FILENO, endstring, strlen(endstring));
|
||||
|
||||
if (post_processed_line.need_free == 1) free(post_processed_line.line_str);
|
||||
|
||||
line_number++;
|
||||
found_char = strtok(NULL, "\r\n"); // I really do not like this repetition
|
||||
}
|
||||
//no more lines in buffer
|
||||
}
|
||||
|
||||
|
||||
|
||||
void supervise(int master_fd, int child_pid){
|
||||
fcntl(master_fd, F_SETFL, O_NONBLOCK);
|
||||
usleep(300*1000); //wait for child shell to init; bad practice, but it works for now
|
||||
|
||||
char *child_out_roll_buffer = (char*) malloc(sizeof(char) * (BUFCHUNKSIZE+BUFSAFEPAD+1));
|
||||
char *parent_in_buffer = (char*) malloc(sizeof(char) * (BUFCHUNKSIZE+BUFSAFEPAD+1));
|
||||
|
||||
while(1){
|
||||
//read child stdout to child_out_roll_buffer
|
||||
//send to processing & output
|
||||
int read_loop_no = 0;
|
||||
while(1){ //continuely read until none left
|
||||
memset(child_out_roll_buffer, 0, BUFCHUNKSIZE+BUFSAFEPAD);
|
||||
errno = 0; //force reset errno
|
||||
ssize_t read_size = read(master_fd, &child_out_roll_buffer[0], BUFCHUNKSIZE - 0);
|
||||
if (read_size > 0) {
|
||||
parsebuffer(child_out_roll_buffer, read_size, read_loop_no);
|
||||
read_loop_no++;
|
||||
continue;
|
||||
}
|
||||
if (read_size == -1 && errno == EAGAIN) break; //read would block (no more data and buffer contents are already processed)
|
||||
//fallthrough read_size == 0
|
||||
DEBUG_PRINT("read_size=0: EOF\n");
|
||||
printf("Reached EOF. child exit? exiting...\n");
|
||||
exit(0);
|
||||
}
|
||||
//read stdin
|
||||
//send to child
|
||||
memset(parent_in_buffer, 0, BUFCHUNKSIZE);
|
||||
strncpy(parent_in_buffer, readline(ps1), BUFCHUNKSIZE-1);
|
||||
write(master_fd, parent_in_buffer, strlen(parent_in_buffer));
|
||||
write(master_fd, "\n", 1);
|
||||
|
||||
usleep(100*1000);
|
||||
}
|
||||
|
||||
free(child_out_roll_buffer);
|
||||
free(parent_in_buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void child_process(char *argv[]){
|
||||
execl(argv[1], argv[1], NULL);
|
||||
}
|
||||
|
||||
void processline(const char *line, int first_line){
|
||||
size_t line_length = strlen(line);
|
||||
char copyline[line_length+3];
|
||||
copyline[0] = '^';
|
||||
strncpy(©line[1], line, line_length); //yes, I know this is "jank" its fine tho. (see next)
|
||||
// 1. line *should* always be NULL terminated
|
||||
// 2. line is ALWAYS < 4097
|
||||
copyline[line_length+1] = '$';
|
||||
copyline[line_length+2] = '\0';
|
||||
//strncat(copyline, "$", 2);
|
||||
char *newline = (char *)©line;
|
||||
char endstring[] = KNRM"\n";
|
||||
//if (first_line) newline = str_replace(newline, "^", "^User Input: ");
|
||||
if (first_line) write(STDOUT_FILENO, ps1_ack, strlen(ps1_ack));
|
||||
for(unsigned int i = 0; i<(sizeof(replace_rules)/sizeof(replace_rules[0])); i++){
|
||||
newline = str_replace(newline, replace_rules[i][0], replace_rules[i][1]);
|
||||
//write(STDOUT_FILENO, debugstring, strlen(debugstring));
|
||||
if (newline == NULL) {
|
||||
newline = copyline;
|
||||
}
|
||||
}
|
||||
write(STDOUT_FILENO, newline+1, strlen(newline)-2);
|
||||
if (newline != NULL) free(newline);
|
||||
write(STDOUT_FILENO, endstring, strlen(endstring));
|
||||
}
|
||||
|
||||
|
||||
void processbuffer(char *roll_buffer, size_t read_length, int first_read) {
|
||||
//this is where some optimization could come in with using malloc and then freeing subset of memory; dog garn dynamic memory allocation
|
||||
//int found_index;
|
||||
char *found_char = strtok(roll_buffer, "\r\n");
|
||||
int first_line = 1;
|
||||
while(found_char != NULL){
|
||||
processline(found_char, first_line&&first_read);
|
||||
first_line = 0;
|
||||
found_char = strtok(NULL, "\r\n");
|
||||
}
|
||||
//no more instances
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf(" --- cterm v%s ---\n" , VERSIONSTRING);
|
||||
printf(" -- %d replace rules loaded --\n", (int *)(sizeof(replace_rules)/sizeof(replace_rules[0])));
|
||||
printf(" --- ---\n");
|
||||
printf("\n");
|
||||
COLORTEST();
|
||||
int master;
|
||||
pid_t child_pid;
|
||||
//struct winsize win = {
|
||||
// .ws_col = 80, .ws_row = 24,
|
||||
// .ws_xpixel = 480, .ws_ypixel = 192,
|
||||
//};
|
||||
printbranding();
|
||||
COLORTEST(); //macro for testing
|
||||
|
||||
// sanity checking
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s cmd [args...]\n", argv[0]);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
child_pid = forkpty(&master, NULL, NULL, NULL);
|
||||
if (child_pid == -1) {
|
||||
|
||||
|
||||
int master_fd;
|
||||
pid_t child_pid;
|
||||
//if the pty window size is to be assigned. shoudnt be a concern since only used by tui programs
|
||||
/*struct winsize win = {
|
||||
.ws_col = 80, .ws_row = 24,
|
||||
.ws_xpixel = 480, .ws_ypixel = 192,
|
||||
};*/
|
||||
|
||||
|
||||
child_pid = forkpty(&master_fd, NULL, NULL, NULL);
|
||||
//TODO: Better error checking
|
||||
if (child_pid == -3) {
|
||||
perror("forkpty failed");
|
||||
exit(EX_OSERR);
|
||||
}
|
||||
|
||||
if (child_pid == 0) {
|
||||
child_process(argv);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//remainder is main is the parent process for processing input and shit
|
||||
fcntl(master, F_SETFL, O_NONBLOCK);
|
||||
char *child_out_roll_buffer = (char*) malloc(sizeof(char) * (BUFCHUNKSIZE+BUFSAFEPAD+1));
|
||||
char *parent_in_buffer = (char*) malloc(sizeof(char) * (BUFCHUNKSIZE+BUFSAFEPAD+1));
|
||||
|
||||
usleep(300*1000); //wait for child shell to init; bad practice, but it works for now
|
||||
while(1){
|
||||
// ideally I would want to read from the pipe and buffer the output, rewriting the line on change
|
||||
// whenever it sees a newline, it should send it to the processor and print to stdout, with that newline
|
||||
//CHILD OUTPUT HANDLING
|
||||
// treating the buffer as kind of a FIFO stack thing
|
||||
// strip lines from top and then move leftover to top,
|
||||
// then start reading where we left off
|
||||
// Later on: it kinda has that behavior, I cant confirm rn, but it "works"
|
||||
int first_read = 1;
|
||||
while(1){
|
||||
memset(child_out_roll_buffer, 0, BUFCHUNKSIZE+BUFSAFEPAD);
|
||||
ssize_t read_count = read(master, &child_out_roll_buffer[0], BUFCHUNKSIZE - 0);
|
||||
if (read_count == 0 ) {
|
||||
DEBUG_PRINT("EOF\n");
|
||||
exit(0);
|
||||
}
|
||||
if (read_count == -1){
|
||||
if(errno == EAGAIN){ //errored because read would block io
|
||||
break;
|
||||
} else {
|
||||
DEBUG_PRINT("I/O \"Error\" (Child Exited?) %d\n", errno);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
//process da block then write it
|
||||
processbuffer(child_out_roll_buffer, read_count, first_read);
|
||||
first_read = 0;
|
||||
}
|
||||
|
||||
//INPUT HANDLING
|
||||
memset(parent_in_buffer, 0, BUFCHUNKSIZE);
|
||||
strncpy(parent_in_buffer, readline(ps1), BUFCHUNKSIZE-1);
|
||||
write(master, parent_in_buffer, strlen(parent_in_buffer));
|
||||
write(master, "\n", 1);
|
||||
|
||||
usleep(100*1000);
|
||||
}
|
||||
}
|
||||
supervise(master_fd, child_pid);
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <debug.h>
|
||||
|
||||
//https://stackoverflow.com/a/779960/8229149
|
||||
char *str_replace(char *orig, char *rep, char *with) {
|
||||
char *result; // the return string
|
||||
|
|
@ -24,7 +27,7 @@ char *str_replace(char *orig, char *rep, char *with) {
|
|||
|
||||
// count the number of replacements needed
|
||||
ins = orig;
|
||||
for (count = 0; tmp = strstr(ins, rep); ++count) {
|
||||
for (count = 0; (tmp = strstr(ins, rep)); ++count) {
|
||||
ins = tmp + len_rep;
|
||||
}
|
||||
|
||||
|
|
@ -47,4 +50,50 @@ char *str_replace(char *orig, char *rep, char *with) {
|
|||
}
|
||||
strcpy(tmp, orig);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* char *str_index_replace(char *orig, int rep_s, int rep_e, char *with) {
|
||||
// Ugh, Re-worked the preceding str_replace function to work with indexes
|
||||
char *result; // the return string
|
||||
char *ins; // the next insert point
|
||||
char *tmp; // varies
|
||||
int len_rep; // length of rep (the string to remove)
|
||||
int len_with; // length of with (the string to replace rep with)
|
||||
int len_front; // distance between rep and end of last rep
|
||||
|
||||
// sanity checks and initialization
|
||||
if (!orig || !rep_e){
|
||||
DEBUG_ERROR("[orig or rep_e is false] *orig=%p; rep_s=%d, rep_e=%d\n", 67, orig, rep_s, rep_e);
|
||||
return NULL;
|
||||
}
|
||||
len_rep = rep_e - rep_s;
|
||||
if (len_rep == 0){
|
||||
DEBUG_ERROR("[rep empty]\n", 72);
|
||||
return NULL; // empty rep causes infinite loop during count
|
||||
}
|
||||
if (!with)
|
||||
with = "";
|
||||
len_with = strlen(with);
|
||||
|
||||
tmp = result = malloc(strlen(orig) + (len_with - len_rep) + 1);
|
||||
|
||||
if (!result) {
|
||||
DEBUG_ERROR("[bad malloc]", 83);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// first time through the loop, all the variable are set correctly
|
||||
// from here on,
|
||||
// tmp points to the end of the result string
|
||||
// ins points to the next occurrence of rep in orig
|
||||
// orig points to the remainder of orig after "end of rep"
|
||||
ins = orig + rep_s;
|
||||
len_front = ins - orig;
|
||||
tmp = strncpy(tmp, orig, len_front) + len_front;
|
||||
tmp = strcpy(tmp, with) + len_with;
|
||||
orig += len_front + len_rep; // move to next "end of rep"
|
||||
strcpy(tmp, orig);
|
||||
return result;
|
||||
} */
|
||||
Loading…
Reference in New Issue