hush: plug the leak of expanded heredoc
[oweals/busybox.git] / shell / match.c
1 /*
2  * ##/%% variable matching code ripped out of ash shell for code sharing
3  *
4  * Copyright (c) 1989, 1991, 1993, 1994
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
8  * was re-ported from NetBSD and debianized.
9  *
10  * This code is derived from software contributed to Berkeley by
11  * Kenneth Almquist.
12  *
13  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
14  *
15  * Original BSD copyright notice is retained at the end of this file.
16  */
17 #ifdef STANDALONE
18 # include <stdbool.h>
19 # include <stdio.h>
20 # include <stdlib.h>
21 # include <string.h>
22 # include <unistd.h>
23 #else
24 # include "libbb.h"
25 #endif
26 #include <fnmatch.h>
27 #include "match.h"
28
29 #define pmatch(a, b) !fnmatch((a), (b), 0)
30
31 char *scanleft(char *string, char *pattern, bool zero)
32 {
33         char c;
34         char *loc = string;
35
36         do {
37                 int match;
38                 const char *s;
39
40                 c = *loc;
41                 if (zero) {
42                         *loc = '\0';
43                         s = string;
44                 } else
45                         s = loc;
46                 match = pmatch(pattern, s);
47                 *loc = c;
48
49                 if (match)
50                         return loc;
51
52                 loc++;
53         } while (c);
54
55         return NULL;
56 }
57
58 char *scanright(char *string, char *pattern, bool zero)
59 {
60         char c;
61         char *loc = string + strlen(string);
62
63         while (loc >= string) {
64                 int match;
65                 const char *s;
66
67                 c = *loc;
68                 if (zero) {
69                         *loc = '\0';
70                         s = string;
71                 } else
72                         s = loc;
73                 match = pmatch(pattern, s);
74                 *loc = c;
75
76                 if (match)
77                         return loc;
78
79                 loc--;
80         }
81
82         return NULL;
83 }
84
85 #ifdef STANDALONE
86 int main(int argc, char *argv[])
87 {
88         char *string;
89         char *op;
90         char *pattern;
91         bool zero;
92         char *loc;
93
94         int i;
95
96         if (argc == 1) {
97                 puts(
98                         "Usage: match <test> [test...]\n\n"
99                         "Where a <test> is the form: <string><op><match>\n"
100                         "This is to test the shell ${var#val} expression type.\n\n"
101                         "e.g. `match 'abc#a*'` -> bc"
102                 );
103                 return 1;
104         }
105
106         for (i = 1; i < argc; ++i) {
107                 size_t off;
108                 scan_t scan;
109
110                 printf("'%s': ", argv[i]);
111
112                 string = strdup(argv[i]);
113                 off = strcspn(string, "#%");
114                 if (!off) {
115                         printf("invalid format\n");
116                         free(string);
117                         continue;
118                 }
119                 op = string + off;
120                 scan = pick_scan(op[0], op[1], &zero);
121                 pattern = op + 1;
122                 if (op[0] == op[1])
123                         op[1] = '\0', ++pattern;
124                 op[0] = '\0';
125
126                 loc = scan(string, pattern, zero);
127
128                 if (zero) {
129                         printf("'%s'\n", loc);
130                 } else {
131                         *loc = '\0';
132                         printf("'%s'\n", string);
133                 }
134
135                 free(string);
136         }
137
138         return 0;
139 }
140 #endif