From a0ef1e229f20ea97d5538c8c4a8f1b6045af0c0c Mon Sep 17 00:00:00 2001 From: epoch Date: Sun, 14 Nov 2021 04:26:25 +0000 Subject: urimatchpairs is new, urigetline got rewritten in C and WEW is it fast now. compare with .sh version. --- urigetline | 29 -------------- urigetline.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ urigetline.sh | 60 ++++++++++++++++++++++++++++ urimatchpairs.c | 23 +++++++++++ 4 files changed, 201 insertions(+), 29 deletions(-) delete mode 100755 urigetline create mode 100644 urigetline.c create mode 100755 urigetline.sh create mode 100644 urimatchpairs.c diff --git a/urigetline b/urigetline deleted file mode 100755 index 3f6bb51..0000000 --- a/urigetline +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -uri="$1" -### old way. -# line="$(grep "^${scheme}:" ~/.config/uristart.conf | cut -d: -f2- | sed 's/^[ \t]*//g' | sed 's/\\/\\\\/g')" - -if [ ! "$uristart_config" ];then - uristart_config=~/.config/uristart.conf -fi - -### fancy way. -grep '^[^#]' "$uristart_config" \ - | while read -r l;do - uritmp="$uri" - uritmp="$(printf "%s\n" "$l" \ - | cut -d: -f1 \ - | tr ' ' '\n' \ - | paste '-d ' - - \ - | while read -r a b;do - uritmp="$(printf "%s\n" "${uritmp}" | urimatch "$a" "$b")" - printf "%s\n" "$uritmp" - done | tail -n1)" - if [ "$uritmp" ];then - printf '%s\n' "$l" - break - fi - done \ - | cut -d: -f2- \ - | sed 's/^[ \t]*//g' \ - | sed 's/\\/\\\\/g' diff --git a/urigetline.c b/urigetline.c new file mode 100644 index 0000000..2d6cd28 --- /dev/null +++ b/urigetline.c @@ -0,0 +1,118 @@ +#include "uri.h" +#include +#include +#include +#include + +#define LINE_LENGTH 1024 + +#define MATCH_UNEXIST 0 +#define MATCH_PATTERN 1 +#define MATCH_REVERSE -1 + +// return 1 if the match and rule should have the main function print this URL. +int match(char rule,char *part,char *arg) { + switch(rule) { + case MATCH_UNEXIST: + if(part == 0) return 1; + break; + case MATCH_REVERSE: + if(part) { + if(!fnmatch(arg,part,FNM_NOESCAPE)) return 0; + else return 1; + } + break; + case MATCH_PATTERN: + if(part) if(!fnmatch(arg,part,FNM_NOESCAPE)) return 1; + break; + default: + fprintf(stderr,"oh god. what the hell happened to get here?\n"); + break; + } + return 0; +} + +int main(int argc,char *argv[]) {//argument needs to be the URI + int j; + int ret=1; + struct uri u; + char matches; + char rule=MATCH_PATTERN; + char *line=malloc(LINE_LENGTH); + char *a,*b,*c; + char *command; + char all=0; + if(argc > 1) { + if(!strcmp(argv[1],"-a")) { + all=1; + argv++; + argc--; + } + } + if(argc < 2) { + fprintf(stderr,"usage: urigetline [-a] uri < uristart.conf\n"); + return 1; + } + urifromline(&u,argv[1]);//only argv[1] is a URI? + while(fgets(line,LINE_LENGTH-1,stdin)) {//each line comes from the config. we need to split it on spaces. + if(strchr(line,'\r')) *strchr(line,'\r')=0; + if(strchr(line,'\n')) *strchr(line,'\n')=0; + if(*line == '#') continue; //skip this line too. comment. + if((command=strchr(line,':'))) { + *command=0; + command++; + while(*command == '\t') command++; + } else continue;//skip this line. needs at least one : to work.. + a=line; + matches=1; + for(;a;) { + rule=MATCH_PATTERN; + j=0; + switch(a[0]) { + case '-': j=1; rule=MATCH_PATTERN; break; + case 'n': j=1; rule=MATCH_UNEXIST; break; + case 'r': j=1; rule=MATCH_REVERSE; break; + default: break; + } + b=0; + c=0; + if(rule != MATCH_UNEXIST) { + if(!(b=strchr(a,' '))) { + fprintf(stderr,"argument '%s' wants a value in the next argument and didn't get it. throwing a fit.\n",a); + return 2; + } + *b=0; b++; + if((c=strchr(b,' '))) {//not required + *c=0; c++; + } + } else { + if((c=strchr(a,' '))) { + *c=0; c++; + } + } + switch(a[j]) { + case 's': if(!match(rule,u.scheme,b)) { matches=0;} break; + case 'u': if(!match(rule,u.username,b)) { matches=0;} break; + case 'k': if(!match(rule,u.password,b)) { matches=0;} break; + case 'd': if(!match(rule,u.domain,b)) { matches=0;} break; + case 'P': if(!match(rule,u.port,b)) { matches=0;} break; + case 'p': if(!match(rule,u.path,b)) { matches=0;} break; + case 'q': if(!match(rule,u.query_string,b)) { matches=0;} break; + case 'f': if(!match(rule,u.fragment_id,b)) { matches=0;} break; + break; + default: + fprintf(stderr,"unknown url part letter! %s\n",a); + return 3; + } + //if(b) printf("two: %s %s\n",a,b); + //else printf("one: %s\n",a); + a=c; + } + if(matches) { + //printf("comm: %s\n",command); + printf("%s\n",command); + if(!all) return ret;//bail early if we only need first match + } + } + return ret; +} diff --git a/urigetline.sh b/urigetline.sh new file mode 100755 index 0000000..8589880 --- /dev/null +++ b/urigetline.sh @@ -0,0 +1,60 @@ +#!/bin/bash +### this script reads a config from stdin +### and does multiple urimatches on the uri argument. +### can optionall use -a to output all matching. +### stdin format is: +### [^\t]+:[ \t]+command\n + +if [ "$1" = "-a" ];then + all=1 + shift +fi +uri="$1" +### old way. +# line="$(grep "^${scheme}:" ~/.config/uristart.conf | cut -d: -f2- | sed 's/^[ \t]*//g' | sed 's/\\/\\\\/g')" + +### going to use urimatchpairs until I get the whole thing rewritten in C +grep '^[^#]' \ + | while read -r l;do + uritmp="$uri" + uritmp="$(urimatchpairs $(printf "%s\n" "$l" | cut -d: -f1) \ + | while read -r a b;do + #printf "pair: '%s' '%s'\n" "$a" "$b" >&2 + uritmp="$(printf "%s\n" "${uritmp}" | urimatch $a $b)" + printf "%s\n" "${uritmp}" + done | tail -n1)" + if [ "$uritmp" ];then + #printf 'matching line: %s\n' "$l" >&2 + printf "%s\n" "$l" + if [ ! "$all" ];then + break + fi + fi + done \ + | cut -d: -f2- \ + | sed 's/^[ \t]*//g' \ + | sed 's/\\/\\\\/g' + +### previous version that doesn't work right for some of the match syntaxes +#grep '^[^#]' \ +# | while read -r l;do +# uritmp="$uri" +# uritmp="$(printf "%s\n" "$l" \ +# | cut -d: -f1 \ +# | tr ' ' '\n' \ +# | paste '-d ' - - \ +# | while read -r a b;do +# uritmp="$(printf "%s\n" "${uritmp}" | urimatch $a $b)" +# printf "%s\n" "$uritmp" +# done | tail -n1)" +# if [ "$uritmp" ];then +# printf 'matching line: %s\n' "$l" >&2 +# printf '%s\n' "$l" +# if [ ! "$all" ]; then +# break +# fi +# fi +# done \ +# | cut -d: -f2- \ +# | sed 's/^[ \t]*//g' \ +# | sed 's/\\/\\\\/g' diff --git a/urimatchpairs.c b/urimatchpairs.c new file mode 100644 index 0000000..6da5d92 --- /dev/null +++ b/urimatchpairs.c @@ -0,0 +1,23 @@ +#include + +int main(int argc,char *argv[]) { + int i,j; + for(i=1;i