~ubuntu-branches/ubuntu/raring/whichman/raring

« back to all changes in this revision

Viewing changes to .pc/10_skip_duplicates.patch/ftwhich.c

  • Committer: Package Import Robot
  • Author(s): Robert Luberda
  • Date: 2012-02-19 16:05:46 UTC
  • Revision ID: package-import@ubuntu.com-20120219160546-nd61zqumiov4zvbl
Tags: 2.4-7
* Switch to debhelper v9 and tiny rules file.
* Rename & refresh patches with gbp-pq import/export.
* Fix lintian's `spelling-error-in-copyright'.
* debian/rules: remove .pc/.dpkg-source-unapply file in rules.
  This fixes broken behaviour of dpkg-buildpackage (see Bug#649521).
* debian/control:
  + Standards-Version: 3.9.2 (no changes);
  + add VCS fields;
  + sort dependency fields with wrap-and-sort.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* vim: set sw=8 ts=8 si et: */
2
 
/*
3
 
 * Author: Guido Socher. This program is distributed
4
 
 * under the terms of the Gnu Public License (GPL). 
5
 
 */
6
 
#include <stdio.h>
7
 
#include <string.h>
8
 
#include <sys/types.h>
9
 
#include <sys/stat.h>
10
 
#include <dirent.h>
11
 
#include <ctype.h>
12
 
#include <stdlib.h>
13
 
#include "levdist.h"
14
 
 
15
 
static void help();
16
 
static char **splitpath();
17
 
static int checkftype(char *path, char *filename);
18
 
static void matchfilename(char *path, char *key);
19
 
static int streq(const char *a,const char *b);
20
 
 
21
 
/*global for simplicity:*/
22
 
static int printdist=0;
23
 
static int casesensitive=0;
24
 
static int nomatchfound=1;
25
 
/*matchlimit indicates the tolerance level for Lev. Dist search
26
 
 *-2 not set, 
27
 
 * 0 = exact match with wildcards,
28
 
 * 1-255 max distance value*/
29
 
static int matchlimit=-2;
30
 
 
31
 
 
32
 
int main(int argc, char *argv[])
33
 
{
34
 
        char searchkey[MAXLEN +1];
35
 
        char **pathcomp;
36
 
        int optnum;
37
 
        char *c,*oarg;
38
 
 
39
 
        if (argc < 2 ) help();
40
 
        /*
41
 
         * After this while loop. argv[0] is the next argument if available
42
 
         *
43
 
         * options that take an argument write *c=0;break; others write
44
 
         * "c++;break;"
45
 
         *
46
 
         * This parser looks a bit complicated but it can take options
47
 
         * like -23 and -ac is the same as "-a -c"
48
 
         */
49
 
        optnum=argc;
50
 
        while (--optnum>0) {
51
 
                argv++;
52
 
                c = *argv; /* c is pointer to one argument/option */
53
 
                if (*c != '-'){
54
 
                        argv--;
55
 
                        break; /*stop at the first non option argument*/
56
 
                }
57
 
                c++;
58
 
                if (*c == '-' && *(c + 1)=='\0'){
59
 
                        /* you can write a double -- to stop option
60
 
                         * parsing. This is useful if you need to search
61
 
                         * for a string that is called "-something" */
62
 
                         --optnum;
63
 
                         break; /*stop option parsing*/
64
 
                }
65
 
                while (*c) {
66
 
                        switch (*c) {
67
 
                        case 'h':
68
 
                                help();
69
 
                                /*no break, help does not return*/
70
 
                        case 'p':
71
 
                                printdist=1;
72
 
                                c++;break;
73
 
                        case 'I':
74
 
                                casesensitive=1;
75
 
                                c++;break;
76
 
                        case 't':
77
 
                                /* you can write -t11 or -t 11*/
78
 
                                /* first the normal -t11 case: */
79
 
                                oarg=c+1;
80
 
                                /* then the -t 11 case: */
81
 
                                if(*(c + 1)=='\0'){
82
 
                                        if(--optnum) oarg=*++argv;
83
 
                                }
84
 
                                matchlimit = atoi(oarg);
85
 
                                if (matchlimit > 255 || matchlimit <0) matchlimit = 255;
86
 
                                *c=0;break;
87
 
                        default:
88
 
                                if (isdigit((int)*c)){
89
 
                                        if (matchlimit !=-1 ){
90
 
                                                /*ignore -e -t1 */
91
 
                                                matchlimit = atoi(c);
92
 
                                                if (matchlimit > 255 || matchlimit <0) matchlimit = 255;
93
 
                                        }
94
 
                                }else{
95
 
                                        fprintf(stderr,"ERROR: No such option. Use -h to get help.\n");
96
 
                                        exit(1);
97
 
                                }
98
 
                                *c=0;
99
 
                        }
100
 
                }
101
 
        }
102
 
        if (optnum<0) optnum=0; /* can be less then zero due to a option
103
 
                                 * with arg at last pos and missing arg*/
104
 
        /*
105
 
         *optnum  is now the number of argmunts left after
106
 
         *option parsing. Example: option a,c take no arg, option b has arg:
107
 
         *                         thisprogram -a -b xx -c d e
108
 
         *                         This results in:
109
 
         *                         optnum==2 and argv[1] points to d
110
 
         *                         argv[2] points to e
111
 
         */ 
112
 
        if (optnum != 1) {
113
 
                /* you must provide exactly one argument */
114
 
                help();
115
 
                /*help does not return */
116
 
        }
117
 
        strncpy(searchkey, argv[1],MAXLEN);
118
 
        if (matchlimit == -2){
119
 
                /*tolerance for Levenshtein Distance search: */
120
 
                matchlimit = stdtolerance(searchkey);
121
 
        }
122
 
 
123
 
        pathcomp = splitpath();
124
 
        while (*pathcomp) {
125
 
                matchfilename(*pathcomp, searchkey);
126
 
                pathcomp++;
127
 
        }
128
 
        return (nomatchfound);
129
 
}
130
 
/*__END OF MAIN__*/
131
 
 
132
 
/*
133
 
 * check that the file is a normal executable.
134
 
 * The abs. path to the file is "path/filename"
135
 
 * Return 1 if it is normal executable or a link to an normal executable
136
 
 */
137
 
#define MAXFULLPATHLEN 500
138
 
int checkftype(char *path, char *filename)
139
 
{
140
 
        struct stat stbuf;
141
 
        static char fullpath[MAXFULLPATHLEN];
142
 
        int i;
143
 
        /*construct the full path to the file:*/
144
 
        i=0;
145
 
        while(*path && i < MAXFULLPATHLEN-7){ /* -7 so, we have some room */
146
 
                fullpath[i]=*path;
147
 
                i++;path++;
148
 
        }
149
 
        if (fullpath[i-1]!='/'){
150
 
                fullpath[i]='/';
151
 
                i++;
152
 
        }
153
 
        while(*filename && i < MAXFULLPATHLEN-1){
154
 
                fullpath[i]=*filename;
155
 
                i++;filename++;
156
 
        }
157
 
        fullpath[i]='\0';
158
 
        /*check if file exists:*/
159
 
        if (stat(fullpath,&stbuf)!=0) return(0);
160
 
        /*not a regular file*/
161
 
        if ((stbuf.st_mode & S_IFREG)==0) return(0);
162
 
        /* test if executable for user or grp or others */
163
 
        if ((stbuf.st_mode & S_IXUSR) || (stbuf.st_mode & S_IXGRP)\
164
 
                ||(stbuf.st_mode & S_IXOTH)) return(1);
165
 
        return(0);
166
 
}
167
 
/*
168
 
 * match all entries in the directory variable path points to
169
 
 * against the key.
170
 
 * This function sets the global variable nomatchfound
171
 
 */
172
 
void matchfilename(char *path, char *key)
173
 
{
174
 
        int dist;
175
 
        DIR *dp;
176
 
        struct dirent *entry;
177
 
        if ((dp = opendir(path)) != NULL) {
178
 
                while ((entry = readdir(dp)) != NULL) {
179
 
                        /*ignore . or .. or .file: */
180
 
                        if (*(entry->d_name) == '.') continue; 
181
 
                        dist=levdist(entry->d_name, key, matchlimit,casesensitive);
182
 
                        if (dist != -1 && checkftype(path,entry->d_name)){
183
 
                                if (printdist) printf("%03d ",dist);
184
 
                                printf("%s/%s\n", path, entry->d_name);
185
 
                                nomatchfound = 0;
186
 
                        }
187
 
                }
188
 
                closedir(dp);
189
 
        }
190
 
}
191
 
 
192
 
 
193
 
/*
194
 
 * split PATH into substrings and return a pointer to 
195
 
 * a 2 dimmentional array with all the sub-strings of the
196
 
 * PATH. 
197
 
 */
198
 
char **splitpath()
199
 
{
200
 
        char *spath; /* search path */
201
 
        char *cspath;/* copy of search path */
202
 
        static char **pathcomp;
203
 
        int i=0;
204
 
        int notseen=1;
205
 
        char *start;
206
 
        int compind = 0;        /* index of *pathcomp[] */
207
 
        int complen = 1;        /* len of one component in the path + 16 */
208
 
 
209
 
        spath = (char *) getenv("PATH");
210
 
        if (spath == NULL || *spath == '\0') {
211
 
                fprintf(stderr,"Warning: PATH not defined, using /bin:/usr/bin\n");
212
 
                spath="/bin:/usr/bin";
213
 
        }
214
 
        /* make a copy that is static */
215
 
        cspath = (char *)malloc(strlen(spath) + 2);
216
 
        strcpy(cspath, spath);
217
 
        start = cspath;
218
 
        /* count the number of colons in the path to find how many
219
 
         * components we have in the path */
220
 
        while (*cspath) {
221
 
                if (*cspath == ':') i++;
222
 
                cspath++;
223
 
        }
224
 
        i+=3; /*some space in case we have corruped path below*/
225
 
        pathcomp=(char **)malloc(sizeof(char *)*i);
226
 
        /* split the path by replacing : with \0 */
227
 
        cspath = start;
228
 
        pathcomp[compind]=cspath;
229
 
        while (*cspath) {
230
 
                if (*cspath == ':') {
231
 
                        *cspath = '\0';
232
 
                        if (complen > 1) { /*ignore zero length comp. e.g :: */
233
 
                                /* now check if it is a duplicate path 
234
 
                                 * component that we can just ignore: */
235
 
                                i=0;notseen=1;
236
 
                                while(notseen && i < compind){
237
 
                                        if(streq(pathcomp[compind],pathcomp[i])){
238
 
                                                notseen=0;
239
 
                                        }
240
 
                                        i++;
241
 
                                }
242
 
                                if (notseen) compind++;
243
 
                        }
244
 
                        /* remove any tailing slashes but not if it is 
245
 
                         * only the root dir (just a "/") */
246
 
                        if (complen > 2 && *(cspath-1) == '/') *(cspath-1)='\0';
247
 
                        pathcomp[compind] = cspath+1;
248
 
                        complen = 0;
249
 
                }
250
 
                cspath++;
251
 
                complen++;
252
 
        }
253
 
        if (complen < 2){
254
 
                /*we have some corrupted path, this happens when you have a
255
 
                 *colon at the end of the path */
256
 
                pathcomp[compind] = NULL;   /*terminate */
257
 
        }else{
258
 
                /* now check if the last one is a duplicate path 
259
 
                 * component that we can just ignore: */
260
 
                i=0;notseen=1;
261
 
                while(notseen && i < compind){
262
 
                        if(streq(pathcomp[compind],pathcomp[i])){
263
 
                                notseen=0;
264
 
                        }
265
 
                        i++;
266
 
                }
267
 
                if (notseen) compind++;
268
 
                pathcomp[compind] = NULL;   /*terminate */
269
 
        }
270
 
        return (&pathcomp[0]);
271
 
}
272
 
/* return 1 if the 2 strings a and b are equal */
273
 
int streq(const char *a,const char *b){
274
 
        while(*a && *b){
275
 
                if(*a != *b) return(0);
276
 
                a++;b++;
277
 
        }
278
 
        /* both must be at \0 */
279
 
        if(*a || *b) return(0);
280
 
        return(1);
281
 
}
282
 
/*
283
 
 * help
284
 
 */
285
 
void help()
286
 
{
287
 
printf("ftwhich -- fault tolerant approximate search command for programs\n\
288
 
\n\
289
 
USAGE:  ftwhich [-#hIp][-t#] [--] program-name\n\
290
 
\n\
291
 
Supported wildcards: * -- any arbitrary number of character\n\
292
 
                     ? -- one character\n\
293
 
\n\
294
 
OPTIONS: -h  this help\n\
295
 
         -I  search case sensitive (default is case in-sensitive)\n\
296
 
         -p  print the actual distance (tolerance) value in front of the\n\
297
 
             file name.\n\
298
 
         -#  set fault tolerance level to # (integer in the range 0-255)\n\
299
 
             It specifies the maximum distance. This is the number of\n\
300
 
             errors permitted for finding the approximate match.\n\
301
 
         -t# same as -# for backward compatibility\n\
302
 
\n\
303
 
With no option specified search is fault tolerant using a tolerance\n\
304
 
level of: (string length of searchpattern - number of wildcards)/6 +1\n");
305
 
printf("%s\n",MYVERSION);
306
 
exit(0);
307
 
}
308
 
/*__END__*/