summaryrefslogtreecommitdiff
path: root/urigetline.c
blob: 4c5c7b4acc135765d7d78074b3c4ce7117eafb6b (plain) (blame)
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;) {
      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;
}