1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#include "uri.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fnmatch.h>
#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(signed 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;
signed char rule=MATCH_PATTERN;
char *line=malloc(LINE_LENGTH);
char *a,*b,*c;
char *command;
char all=0;
int verbose=0;
if(argc > 1) {
if(!strcmp(argv[1],"-a")) {
all=1;
argv++;
argc--;
}
if(!strcmp(argv[1],"-v")) {
verbose++;
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?
for(;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(strlen(line) == 0) continue; //skip empty lines.
if((command=strstr(line,":\t"))) {//this is the "real" separator between match pattern and command
*command=0;
command++;
while(*command == '\t') command++;//and command may have leading tabs that are ignored.
if(verbose) fprintf(stderr,"loading config line: '%s'\n",line);
} else {
fprintf(stderr,"invalid line: '%s'\n",line);
continue;//skip this line. needs at least one ":\t" to work.
}
a=line;
matches=1;
for(;a && *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. (pass -v to urigetline to help debug)\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;
}
|