diff options
author | Eric Andersen <andersen@codepoet.org> | 1999-10-22 04:30:20 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 1999-10-22 04:30:20 +0000 |
commit | aa0765e11bdeba5c5abf745369a8430c8311d60c (patch) | |
tree | 3593c1a2ff03bfa79982fa12b55c9489f969e057 | |
parent | c49960189a04b73e033016bd0f43fbb950f800e1 (diff) | |
download | busybox-w32-aa0765e11bdeba5c5abf745369a8430c8311d60c.tar.gz busybox-w32-aa0765e11bdeba5c5abf745369a8430c8311d60c.tar.bz2 busybox-w32-aa0765e11bdeba5c5abf745369a8430c8311d60c.zip |
Added regexp support, fixed Changelog.
-rw-r--r-- | Changelog | 76 | ||||
-rw-r--r-- | busybox.def.h | 5 | ||||
-rw-r--r-- | find.c | 23 | ||||
-rw-r--r-- | findutils/find.c | 23 | ||||
-rw-r--r-- | findutils/grep.c | 46 | ||||
-rw-r--r-- | grep.c | 46 | ||||
-rw-r--r-- | internal.h | 6 | ||||
-rw-r--r-- | regexp.c | 826 | ||||
-rw-r--r-- | smtpout | 2 | ||||
-rw-r--r-- | utility.c | 151 |
10 files changed, 1006 insertions, 198 deletions
@@ -1,7 +1,81 @@ | |||
1 | 0.31 | ||
2 | * I added a changelog for version 0.30. | ||
3 | * adjusted find internals to make it smaller, and removed | ||
4 | some redundancy. | ||
5 | * Fixed a segfault in ps when /etc/passwd or /etc/group | ||
6 | are absent. Now will warn you and carry on. | ||
7 | * Added in optional _real_ regular expression support (to be | ||
8 | the basis for a future sed utility). When compiled in, | ||
9 | adds 3.9k. | ||
10 | |||
11 | |||
1 | 0.30 | 12 | 0.30 |
2 | Major changes -- lots of stuff rewritten. Many thanks to Lineo for | 13 | Major changes -- lots of stuff rewritten. Many thanks to Lineo for |
3 | paying me to make these updates. If you have any problems with busybox, | 14 | paying me to make these updates. If you have any problems with busybox, |
4 | or notice any bugs -- please let me know so I can fix it. | 15 | or notice any bugs -- please let me know so I can fix it. These |
16 | changes include: | ||
17 | |||
18 | Core Changes: | ||
19 | * busybox can now invoke apps in two ways: via symlinks to the | ||
20 | busybox binary, and as 'busybox [function] [arguments]...' | ||
21 | * When invoked as busybox, the list of currently compiled in | ||
22 | functions is printed out (no this is not bloat -- the list | ||
23 | has to be there anyway to map invocation name to function). | ||
24 | * busybox no longer parses command lines for apps or displays their | ||
25 | usage info. Each app gets to handle (or not handle) this for | ||
26 | itself. | ||
27 | * Eliminated monadic, dyadic, descend, block_device, and | ||
28 | postprocess. It was cumbersome to have so many programs | ||
29 | cobbled together in this way. Without them, the app is much | ||
30 | more granular. | ||
31 | * All shared code now lives in utility.c, and is properly | ||
32 | ifdef'ed to be only included for those apps requiring it. | ||
33 | * Eliminated struct FileInfo (the basis of monadic, dyadic, etc) | ||
34 | so now each app has the function prototype of (da-dum): | ||
35 | extern int foo_main(int argc, char** argv); | ||
36 | which speeds integration of new apps. | ||
37 | * Adjusted the Makefile to make it easier to | ||
38 | {en|dis}able debugging. | ||
39 | * Changed default compiler optimization to -Os | ||
40 | (optimize for smaller binaries). | ||
41 | |||
42 | App Changes: | ||
43 | * To cope with the new app function prototype and the removal of | ||
44 | monadic, dyadic, etc, the following apps were re-written: | ||
45 | * cat - Works same as always. | ||
46 | * chgrp, chmod, chown - rewrite. Combined into a single | ||
47 | source file. Absorbed patches from Enrique Zanardi <ezanard@debian.org> | ||
48 | that removes the dependency on libc6 libnss* libraries. | ||
49 | * cp - Can now do 'cp -a' can can copy devices, | ||
50 | pipes, symlinks, as well as recursive or non-recursive dir copies. | ||
51 | * fdflush - adjusted to remove dependancy on struct FileInfo. | ||
52 | * find - Now includes some basic regexp matching | ||
53 | which will be the basic of a future mini-sed. | ||
54 | * ln - Same functionality. | ||
55 | * mkdir - Added -p flag to feature set. | ||
56 | * mv - rewrite. | ||
57 | * rm - Added -f flag to feature set. | ||
58 | * rmdir - Same functionality. | ||
59 | * swapon, swapoff - Combined into a single binary. No longer | ||
60 | uses /etc/swaps. swap{on|off} -a uses /etc/fstab instead. | ||
61 | * touch - Same functionality. | ||
62 | * date - adjusted with a patch from Matthew Grant <grantma@anathoth.gen.nz> | ||
63 | to accomodate glibc timezone support. I then ripped out GNU getopt. | ||
64 | * mkswap -- new version merged from util-linux. Can now make >128Meg swaps. | ||
65 | * Replaced the old and star, unstar, and tarcat with the tar | ||
66 | implementation from sash. Now tar behaves as god intended | ||
67 | it to (i.e. tar -xvf <file> and tar -cf <file> <dir> work). | ||
68 | * dd -- rewritten. Can with with files, stdin, stdout. | ||
69 | * Added the following new apps: | ||
70 | * loadfont -- added from debian boot floppies | ||
71 | * chroot -- added based on a patch from Paolo Molaro <lupus@lettere.unipd.it> | ||
72 | * grep -- I just wrote it. Only matches simple strings | ||
73 | * ps -- I just wrote it. Has _no_ options at all, but works. | ||
74 | * fsck_minix, mkfs_minix -- added from util-linux, but I ripped out | ||
75 | internationalization and such to make them smaller. | ||
76 | * sfdisk -- Added from util-linux (minus internationalization and such). | ||
77 | * Probably some other changes that I forgot to document... | ||
78 | |||
5 | -Erik Andersen | 79 | -Erik Andersen |
6 | 80 | ||
7 | 0.28 | 81 | 0.28 |
diff --git a/busybox.def.h b/busybox.def.h index 692f24e49..033ccca84 100644 --- a/busybox.def.h +++ b/busybox.def.h | |||
@@ -40,6 +40,7 @@ | |||
40 | //#define BB_PRINTF | 40 | //#define BB_PRINTF |
41 | #define BB_PS | 41 | #define BB_PS |
42 | #define BB_PWD | 42 | #define BB_PWD |
43 | #define BB_REGEXP | ||
43 | #define BB_REBOOT | 44 | #define BB_REBOOT |
44 | #define BB_RM | 45 | #define BB_RM |
45 | #define BB_RMDIR | 46 | #define BB_RMDIR |
@@ -52,6 +53,8 @@ | |||
52 | //#define BB_TRUE_FALSE // Supplied by ash | 53 | //#define BB_TRUE_FALSE // Supplied by ash |
53 | #define BB_UMOUNT | 54 | #define BB_UMOUNT |
54 | #define BB_UPDATE | 55 | #define BB_UPDATE |
55 | #define BB_UTILITY | ||
56 | #define BB_ZCAT | 56 | #define BB_ZCAT |
57 | //#define BB_GZIP | 57 | //#define BB_GZIP |
58 | // Don't turn BB_UTILITY off. It contains support code | ||
59 | // that compiles to 0 if everything else if turned off. | ||
60 | #define BB_UTILITY | ||
@@ -21,14 +21,15 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "internal.h" | ||
25 | #include "regexp.h" | ||
24 | #include <stdio.h> | 26 | #include <stdio.h> |
25 | #include <unistd.h> | 27 | #include <unistd.h> |
26 | #include <dirent.h> | 28 | #include <dirent.h> |
27 | #include "internal.h" | ||
28 | 29 | ||
29 | 30 | ||
30 | static char* pattern=NULL; | 31 | static char* pattern=NULL; |
31 | static char* directory=NULL; | 32 | static char* directory="."; |
32 | static int dereferenceFlag=FALSE; | 33 | static int dereferenceFlag=FALSE; |
33 | 34 | ||
34 | static const char find_usage[] = "find [path...] [expression]\n" | 35 | static const char find_usage[] = "find [path...] [expression]\n" |
@@ -41,7 +42,7 @@ static int fileAction(const char *fileName, struct stat* statbuf) | |||
41 | { | 42 | { |
42 | if (pattern==NULL) | 43 | if (pattern==NULL) |
43 | fprintf(stdout, "%s\n", fileName); | 44 | fprintf(stdout, "%s\n", fileName); |
44 | else if (match(fileName, pattern) == TRUE) | 45 | else if (find_match(fileName, pattern, TRUE) == TRUE) |
45 | fprintf(stdout, "%s\n", fileName); | 46 | fprintf(stdout, "%s\n", fileName); |
46 | return( TRUE); | 47 | return( TRUE); |
47 | } | 48 | } |
@@ -53,7 +54,7 @@ static int dirAction(const char *fileName, struct stat* statbuf) | |||
53 | 54 | ||
54 | if (pattern==NULL) | 55 | if (pattern==NULL) |
55 | fprintf(stdout, "%s\n", fileName); | 56 | fprintf(stdout, "%s\n", fileName); |
56 | else if (match(fileName, pattern) == TRUE) | 57 | else if (find_match(fileName, pattern, TRUE) == TRUE) |
57 | fprintf(stdout, "%s\n", fileName); | 58 | fprintf(stdout, "%s\n", fileName); |
58 | 59 | ||
59 | dir = opendir( fileName); | 60 | dir = opendir( fileName); |
@@ -71,22 +72,18 @@ static int dirAction(const char *fileName, struct stat* statbuf) | |||
71 | 72 | ||
72 | int find_main(int argc, char **argv) | 73 | int find_main(int argc, char **argv) |
73 | { | 74 | { |
74 | if (argc <= 1) { | ||
75 | dirAction( ".", NULL); | ||
76 | } | ||
77 | |||
78 | /* peel off the "find" */ | 75 | /* peel off the "find" */ |
79 | argc--; | 76 | argc--; |
80 | argv++; | 77 | argv++; |
81 | 78 | ||
82 | if (**argv != '-') { | 79 | if ( argc > 0 && **argv != '-') { |
83 | directory=*argv; | 80 | directory=*argv; |
84 | argc--; | 81 | argc--; |
85 | argv++; | 82 | argv++; |
86 | } | 83 | } |
87 | 84 | ||
88 | /* Parse any options */ | 85 | /* Parse any options */ |
89 | while (**argv == '-') { | 86 | while (argc > 0 && **argv == '-') { |
90 | int stopit=FALSE; | 87 | int stopit=FALSE; |
91 | while (*++(*argv) && stopit==FALSE) switch (**argv) { | 88 | while (*++(*argv) && stopit==FALSE) switch (**argv) { |
92 | case 'f': | 89 | case 'f': |
@@ -120,6 +117,10 @@ int find_main(int argc, char **argv) | |||
120 | break; | 117 | break; |
121 | } | 118 | } |
122 | 119 | ||
123 | dirAction( directory, NULL); | 120 | if (recursiveAction(directory, TRUE, FALSE, FALSE, |
121 | fileAction, fileAction) == FALSE) { | ||
122 | exit( FALSE); | ||
123 | } | ||
124 | |||
124 | exit(TRUE); | 125 | exit(TRUE); |
125 | } | 126 | } |
diff --git a/findutils/find.c b/findutils/find.c index 1db332297..c154cf4e7 100644 --- a/findutils/find.c +++ b/findutils/find.c | |||
@@ -21,14 +21,15 @@ | |||
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "internal.h" | ||
25 | #include "regexp.h" | ||
24 | #include <stdio.h> | 26 | #include <stdio.h> |
25 | #include <unistd.h> | 27 | #include <unistd.h> |
26 | #include <dirent.h> | 28 | #include <dirent.h> |
27 | #include "internal.h" | ||
28 | 29 | ||
29 | 30 | ||
30 | static char* pattern=NULL; | 31 | static char* pattern=NULL; |
31 | static char* directory=NULL; | 32 | static char* directory="."; |
32 | static int dereferenceFlag=FALSE; | 33 | static int dereferenceFlag=FALSE; |
33 | 34 | ||
34 | static const char find_usage[] = "find [path...] [expression]\n" | 35 | static const char find_usage[] = "find [path...] [expression]\n" |
@@ -41,7 +42,7 @@ static int fileAction(const char *fileName, struct stat* statbuf) | |||
41 | { | 42 | { |
42 | if (pattern==NULL) | 43 | if (pattern==NULL) |
43 | fprintf(stdout, "%s\n", fileName); | 44 | fprintf(stdout, "%s\n", fileName); |
44 | else if (match(fileName, pattern) == TRUE) | 45 | else if (find_match(fileName, pattern, TRUE) == TRUE) |
45 | fprintf(stdout, "%s\n", fileName); | 46 | fprintf(stdout, "%s\n", fileName); |
46 | return( TRUE); | 47 | return( TRUE); |
47 | } | 48 | } |
@@ -53,7 +54,7 @@ static int dirAction(const char *fileName, struct stat* statbuf) | |||
53 | 54 | ||
54 | if (pattern==NULL) | 55 | if (pattern==NULL) |
55 | fprintf(stdout, "%s\n", fileName); | 56 | fprintf(stdout, "%s\n", fileName); |
56 | else if (match(fileName, pattern) == TRUE) | 57 | else if (find_match(fileName, pattern, TRUE) == TRUE) |
57 | fprintf(stdout, "%s\n", fileName); | 58 | fprintf(stdout, "%s\n", fileName); |
58 | 59 | ||
59 | dir = opendir( fileName); | 60 | dir = opendir( fileName); |
@@ -71,22 +72,18 @@ static int dirAction(const char *fileName, struct stat* statbuf) | |||
71 | 72 | ||
72 | int find_main(int argc, char **argv) | 73 | int find_main(int argc, char **argv) |
73 | { | 74 | { |
74 | if (argc <= 1) { | ||
75 | dirAction( ".", NULL); | ||
76 | } | ||
77 | |||
78 | /* peel off the "find" */ | 75 | /* peel off the "find" */ |
79 | argc--; | 76 | argc--; |
80 | argv++; | 77 | argv++; |
81 | 78 | ||
82 | if (**argv != '-') { | 79 | if ( argc > 0 && **argv != '-') { |
83 | directory=*argv; | 80 | directory=*argv; |
84 | argc--; | 81 | argc--; |
85 | argv++; | 82 | argv++; |
86 | } | 83 | } |
87 | 84 | ||
88 | /* Parse any options */ | 85 | /* Parse any options */ |
89 | while (**argv == '-') { | 86 | while (argc > 0 && **argv == '-') { |
90 | int stopit=FALSE; | 87 | int stopit=FALSE; |
91 | while (*++(*argv) && stopit==FALSE) switch (**argv) { | 88 | while (*++(*argv) && stopit==FALSE) switch (**argv) { |
92 | case 'f': | 89 | case 'f': |
@@ -120,6 +117,10 @@ int find_main(int argc, char **argv) | |||
120 | break; | 117 | break; |
121 | } | 118 | } |
122 | 119 | ||
123 | dirAction( directory, NULL); | 120 | if (recursiveAction(directory, TRUE, FALSE, FALSE, |
121 | fileAction, fileAction) == FALSE) { | ||
122 | exit( FALSE); | ||
123 | } | ||
124 | |||
124 | exit(TRUE); | 125 | exit(TRUE); |
125 | } | 126 | } |
diff --git a/findutils/grep.c b/findutils/grep.c index a495c62ae..44ca02834 100644 --- a/findutils/grep.c +++ b/findutils/grep.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "internal.h" | 24 | #include "internal.h" |
25 | #include "regexp.h" | ||
25 | #include <stdio.h> | 26 | #include <stdio.h> |
26 | #include <dirent.h> | 27 | #include <dirent.h> |
27 | #include <errno.h> | 28 | #include <errno.h> |
@@ -30,44 +31,17 @@ | |||
30 | #include <time.h> | 31 | #include <time.h> |
31 | #include <ctype.h> | 32 | #include <ctype.h> |
32 | 33 | ||
33 | |||
34 | static const char grep_usage[] = | 34 | static const char grep_usage[] = |
35 | "grep [-ihn]... PATTERN [FILE]...\n" | 35 | "grep [-ihn]... PATTERN [FILE]...\n" |
36 | "Search for PATTERN in each FILE or standard input.\n\n" | 36 | "Search for PATTERN in each FILE or standard input.\n\n" |
37 | "\t-h\tsuppress the prefixing filename on output\n" | 37 | "\t-h\tsuppress the prefixing filename on output\n" |
38 | "\t-i\tignore case distinctions\n" | 38 | "\t-i\tignore case distinctions\n" |
39 | "\t-n\tprint line number with output lines\n\n" | 39 | "\t-n\tprint line number with output lines\n\n" |
40 | #if defined BB_REGEXP | ||
41 | "This version of grep matches full regexps.\n"; | ||
42 | #else | ||
40 | "This version of grep matches strings (not full regexps).\n"; | 43 | "This version of grep matches strings (not full regexps).\n"; |
41 | 44 | #endif | |
42 | |||
43 | /* | ||
44 | * See if the specified needle is found in the specified haystack. | ||
45 | */ | ||
46 | static int search (const char *haystack, const char *needle, int ignoreCase) | ||
47 | { | ||
48 | |||
49 | if (ignoreCase == FALSE) { | ||
50 | haystack = strstr (haystack, needle); | ||
51 | if (haystack == NULL) | ||
52 | return FALSE; | ||
53 | return TRUE; | ||
54 | } else { | ||
55 | int i; | ||
56 | char needle1[BUF_SIZE]; | ||
57 | char haystack1[BUF_SIZE]; | ||
58 | |||
59 | strncpy( haystack1, haystack, sizeof(haystack1)); | ||
60 | strncpy( needle1, needle, sizeof(needle1)); | ||
61 | for( i=0; i<sizeof(haystack1) && haystack1[i]; i++) | ||
62 | haystack1[i]=tolower( haystack1[i]); | ||
63 | for( i=0; i<sizeof(needle1) && needle1[i]; i++) | ||
64 | needle1[i]=tolower( needle1[i]); | ||
65 | haystack = strstr (haystack1, needle1); | ||
66 | if (haystack == NULL) | ||
67 | return FALSE; | ||
68 | return TRUE; | ||
69 | } | ||
70 | } | ||
71 | 45 | ||
72 | 46 | ||
73 | extern int grep_main (int argc, char **argv) | 47 | extern int grep_main (int argc, char **argv) |
@@ -80,7 +54,7 @@ extern int grep_main (int argc, char **argv) | |||
80 | int ignoreCase=FALSE; | 54 | int ignoreCase=FALSE; |
81 | int tellLine=FALSE; | 55 | int tellLine=FALSE; |
82 | long line; | 56 | long line; |
83 | char buf[BUF_SIZE]; | 57 | char haystack[BUF_SIZE]; |
84 | 58 | ||
85 | ignoreCase = FALSE; | 59 | ignoreCase = FALSE; |
86 | tellLine = FALSE; | 60 | tellLine = FALSE; |
@@ -128,21 +102,21 @@ extern int grep_main (int argc, char **argv) | |||
128 | 102 | ||
129 | line = 0; | 103 | line = 0; |
130 | 104 | ||
131 | while (fgets (buf, sizeof (buf), fp)) { | 105 | while (fgets (haystack, sizeof (haystack), fp)) { |
132 | line++; | 106 | line++; |
133 | cp = &buf[strlen (buf) - 1]; | 107 | cp = &haystack[strlen (haystack) - 1]; |
134 | 108 | ||
135 | if (*cp != '\n') | 109 | if (*cp != '\n') |
136 | fprintf (stderr, "%s: Line too long\n", name); | 110 | fprintf (stderr, "%s: Line too long\n", name); |
137 | 111 | ||
138 | if (search (buf, needle, ignoreCase)==TRUE) { | 112 | if (find_match(haystack, needle, ignoreCase) == TRUE) { |
139 | if (tellName==TRUE) | 113 | if (tellName==TRUE) |
140 | printf ("%s: ", name); | 114 | printf ("%s: ", name); |
141 | 115 | ||
142 | if (tellLine==TRUE) | 116 | if (tellLine==TRUE) |
143 | printf ("%ld: ", line); | 117 | printf ("%ld: ", line); |
144 | 118 | ||
145 | fputs (buf, stdout); | 119 | fputs (haystack, stdout); |
146 | } | 120 | } |
147 | } | 121 | } |
148 | 122 | ||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "internal.h" | 24 | #include "internal.h" |
25 | #include "regexp.h" | ||
25 | #include <stdio.h> | 26 | #include <stdio.h> |
26 | #include <dirent.h> | 27 | #include <dirent.h> |
27 | #include <errno.h> | 28 | #include <errno.h> |
@@ -30,44 +31,17 @@ | |||
30 | #include <time.h> | 31 | #include <time.h> |
31 | #include <ctype.h> | 32 | #include <ctype.h> |
32 | 33 | ||
33 | |||
34 | static const char grep_usage[] = | 34 | static const char grep_usage[] = |
35 | "grep [-ihn]... PATTERN [FILE]...\n" | 35 | "grep [-ihn]... PATTERN [FILE]...\n" |
36 | "Search for PATTERN in each FILE or standard input.\n\n" | 36 | "Search for PATTERN in each FILE or standard input.\n\n" |
37 | "\t-h\tsuppress the prefixing filename on output\n" | 37 | "\t-h\tsuppress the prefixing filename on output\n" |
38 | "\t-i\tignore case distinctions\n" | 38 | "\t-i\tignore case distinctions\n" |
39 | "\t-n\tprint line number with output lines\n\n" | 39 | "\t-n\tprint line number with output lines\n\n" |
40 | #if defined BB_REGEXP | ||
41 | "This version of grep matches full regexps.\n"; | ||
42 | #else | ||
40 | "This version of grep matches strings (not full regexps).\n"; | 43 | "This version of grep matches strings (not full regexps).\n"; |
41 | 44 | #endif | |
42 | |||
43 | /* | ||
44 | * See if the specified needle is found in the specified haystack. | ||
45 | */ | ||
46 | static int search (const char *haystack, const char *needle, int ignoreCase) | ||
47 | { | ||
48 | |||
49 | if (ignoreCase == FALSE) { | ||
50 | haystack = strstr (haystack, needle); | ||
51 | if (haystack == NULL) | ||
52 | return FALSE; | ||
53 | return TRUE; | ||
54 | } else { | ||
55 | int i; | ||
56 | char needle1[BUF_SIZE]; | ||
57 | char haystack1[BUF_SIZE]; | ||
58 | |||
59 | strncpy( haystack1, haystack, sizeof(haystack1)); | ||
60 | strncpy( needle1, needle, sizeof(needle1)); | ||
61 | for( i=0; i<sizeof(haystack1) && haystack1[i]; i++) | ||
62 | haystack1[i]=tolower( haystack1[i]); | ||
63 | for( i=0; i<sizeof(needle1) && needle1[i]; i++) | ||
64 | needle1[i]=tolower( needle1[i]); | ||
65 | haystack = strstr (haystack1, needle1); | ||
66 | if (haystack == NULL) | ||
67 | return FALSE; | ||
68 | return TRUE; | ||
69 | } | ||
70 | } | ||
71 | 45 | ||
72 | 46 | ||
73 | extern int grep_main (int argc, char **argv) | 47 | extern int grep_main (int argc, char **argv) |
@@ -80,7 +54,7 @@ extern int grep_main (int argc, char **argv) | |||
80 | int ignoreCase=FALSE; | 54 | int ignoreCase=FALSE; |
81 | int tellLine=FALSE; | 55 | int tellLine=FALSE; |
82 | long line; | 56 | long line; |
83 | char buf[BUF_SIZE]; | 57 | char haystack[BUF_SIZE]; |
84 | 58 | ||
85 | ignoreCase = FALSE; | 59 | ignoreCase = FALSE; |
86 | tellLine = FALSE; | 60 | tellLine = FALSE; |
@@ -128,21 +102,21 @@ extern int grep_main (int argc, char **argv) | |||
128 | 102 | ||
129 | line = 0; | 103 | line = 0; |
130 | 104 | ||
131 | while (fgets (buf, sizeof (buf), fp)) { | 105 | while (fgets (haystack, sizeof (haystack), fp)) { |
132 | line++; | 106 | line++; |
133 | cp = &buf[strlen (buf) - 1]; | 107 | cp = &haystack[strlen (haystack) - 1]; |
134 | 108 | ||
135 | if (*cp != '\n') | 109 | if (*cp != '\n') |
136 | fprintf (stderr, "%s: Line too long\n", name); | 110 | fprintf (stderr, "%s: Line too long\n", name); |
137 | 111 | ||
138 | if (search (buf, needle, ignoreCase)==TRUE) { | 112 | if (find_match(haystack, needle, ignoreCase) == TRUE) { |
139 | if (tellName==TRUE) | 113 | if (tellName==TRUE) |
140 | printf ("%s: ", name); | 114 | printf ("%s: ", name); |
141 | 115 | ||
142 | if (tellLine==TRUE) | 116 | if (tellLine==TRUE) |
143 | printf ("%ld: ", line); | 117 | printf ("%ld: ", line); |
144 | 118 | ||
145 | fputs (buf, stdout); | 119 | fputs (haystack, stdout); |
146 | } | 120 | } |
147 | } | 121 | } |
148 | 122 | ||
diff --git a/internal.h b/internal.h index d23dca31e..cc7bfca11 100644 --- a/internal.h +++ b/internal.h | |||
@@ -130,7 +130,6 @@ int fullRead(int fd, char *buf, int len); | |||
130 | int recursiveAction(const char *fileName, int recurse, int followLinks, int delayDirAction, | 130 | int recursiveAction(const char *fileName, int recurse, int followLinks, int delayDirAction, |
131 | int (*fileAction) (const char *fileName, struct stat* statbuf), | 131 | int (*fileAction) (const char *fileName, struct stat* statbuf), |
132 | int (*dirAction) (const char *fileName, struct stat* statbuf)); | 132 | int (*dirAction) (const char *fileName, struct stat* statbuf)); |
133 | int match(const char* text, const char * pattern); | ||
134 | const char* timeString(time_t timeVal); | 133 | const char* timeString(time_t timeVal); |
135 | 134 | ||
136 | extern void createPath (const char *name, int mode); | 135 | extern void createPath (const char *name, int mode); |
@@ -166,8 +165,9 @@ static inline int clrbit(char * addr,unsigned int nr) | |||
166 | return __res != 0; | 165 | return __res != 0; |
167 | } | 166 | } |
168 | 167 | ||
169 | #endif | 168 | #endif /* inline bitops junk */ |
170 | 169 | ||
171 | 170 | ||
172 | #endif | 171 | |
172 | #endif /* _INTERNAL_H_ */ | ||
173 | 173 | ||
diff --git a/regexp.c b/regexp.c new file mode 100644 index 000000000..6017d79b4 --- /dev/null +++ b/regexp.c | |||
@@ -0,0 +1,826 @@ | |||
1 | /* regexp.c */ | ||
2 | |||
3 | #include "internal.h" | ||
4 | #include "regexp.h" | ||
5 | #include <setjmp.h> | ||
6 | #include <stdio.h> | ||
7 | #include <ctype.h> | ||
8 | |||
9 | |||
10 | #if ( defined BB_GREP || defined BB_FIND ) | ||
11 | |||
12 | /* This also tries to find a needle in a haystack, but uses | ||
13 | * real regular expressions.... The fake regular expression | ||
14 | * version of find_match lives in utility.c. Using this version | ||
15 | * will add 3.9k to busybox... | ||
16 | * -Erik Andersen | ||
17 | */ | ||
18 | extern int find_match(char *haystack, char *needle, int ignoreCase) | ||
19 | { | ||
20 | int status; | ||
21 | struct regexp* re; | ||
22 | re = regcomp( needle); | ||
23 | status = regexec(re, haystack, FALSE, ignoreCase); | ||
24 | free( re); | ||
25 | return( status); | ||
26 | } | ||
27 | |||
28 | |||
29 | /* code swiped from elvis-tiny 1.4 (a clone of vi) and adjusted to | ||
30 | * suit the needs of busybox by Erik Andersen. | ||
31 | * | ||
32 | * From the README: | ||
33 | * "Elvis is freely redistributable, in either source form or executable form. | ||
34 | * There are no restrictions on how you may use it". | ||
35 | * Elvis was written by Steve Kirkendall <kirkenda@cs.pdx.edu> | ||
36 | * | ||
37 | * | ||
38 | * This file contains the code that compiles regular expressions and executes | ||
39 | * them. It supports the same syntax and features as vi's regular expression | ||
40 | * code. Specifically, the meta characters are: | ||
41 | * ^ matches the beginning of a line | ||
42 | * $ matches the end of a line | ||
43 | * \< matches the beginning of a word | ||
44 | * \> matches the end of a word | ||
45 | * . matches any single character | ||
46 | * [] matches any character in a character class | ||
47 | * \( delimits the start of a subexpression | ||
48 | * \) delimits the end of a subexpression | ||
49 | * * repeats the preceding 0 or more times | ||
50 | * NOTE: You cannot follow a \) with a *. | ||
51 | * | ||
52 | * The physical structure of a compiled RE is as follows: | ||
53 | * - First, there is a one-byte value that says how many character classes | ||
54 | * are used in this regular expression | ||
55 | * - Next, each character class is stored as a bitmap that is 256 bits | ||
56 | * (32 bytes) long. | ||
57 | * - A mixture of literal characters and compiled meta characters follows. | ||
58 | * This begins with M_BEGIN(0) and ends with M_END(0). All meta chars | ||
59 | * are stored as a \n followed by a one-byte code, so they take up two | ||
60 | * bytes apiece. Literal characters take up one byte apiece. \n can't | ||
61 | * be used as a literal character. | ||
62 | * | ||
63 | */ | ||
64 | |||
65 | |||
66 | |||
67 | static char *previous; /* the previous regexp, used when null regexp is given */ | ||
68 | static char *previous1; /* a copy of the text from the previous substitution for regsub()*/ | ||
69 | |||
70 | |||
71 | /* These are used to classify or recognize meta-characters */ | ||
72 | #define META '\0' | ||
73 | #define BASE_META(m) ((m) - 256) | ||
74 | #define INT_META(c) ((c) + 256) | ||
75 | #define IS_META(m) ((m) >= 256) | ||
76 | #define IS_CLASS(m) ((m) >= M_CLASS(0) && (m) <= M_CLASS(9)) | ||
77 | #define IS_START(m) ((m) >= M_START(0) && (m) <= M_START(9)) | ||
78 | #define IS_END(m) ((m) >= M_END(0) && (m) <= M_END(9)) | ||
79 | #define IS_CLOSURE(m) ((m) >= M_SPLAT && (m) <= M_QMARK) | ||
80 | #define ADD_META(s,m) (*(s)++ = META, *(s)++ = BASE_META(m)) | ||
81 | #define GET_META(s) (*(s) == META ? INT_META(*++(s)) : *s) | ||
82 | |||
83 | /* These are the internal codes used for each type of meta-character */ | ||
84 | #define M_BEGLINE 256 /* internal code for ^ */ | ||
85 | #define M_ENDLINE 257 /* internal code for $ */ | ||
86 | #define M_BEGWORD 258 /* internal code for \< */ | ||
87 | #define M_ENDWORD 259 /* internal code for \> */ | ||
88 | #define M_ANY 260 /* internal code for . */ | ||
89 | #define M_SPLAT 261 /* internal code for * */ | ||
90 | #define M_PLUS 262 /* internal code for \+ */ | ||
91 | #define M_QMARK 263 /* internal code for \? */ | ||
92 | #define M_CLASS(n) (264+(n)) /* internal code for [] */ | ||
93 | #define M_START(n) (274+(n)) /* internal code for \( */ | ||
94 | #define M_END(n) (284+(n)) /* internal code for \) */ | ||
95 | |||
96 | /* These are used during compilation */ | ||
97 | static int class_cnt; /* used to assign class IDs */ | ||
98 | static int start_cnt; /* used to assign start IDs */ | ||
99 | static int end_stk[NSUBEXP];/* used to assign end IDs */ | ||
100 | static int end_sp; | ||
101 | static char *retext; /* points to the text being compiled */ | ||
102 | |||
103 | /* error-handling stuff */ | ||
104 | jmp_buf errorhandler; | ||
105 | #define FAIL(why) fprintf(stderr, why); longjmp(errorhandler, 1) | ||
106 | |||
107 | |||
108 | |||
109 | |||
110 | /* This function builds a bitmap for a particular class */ | ||
111 | /* text -- start of the class */ | ||
112 | /* bmap -- the bitmap */ | ||
113 | static char *makeclass(char* text, char* bmap) | ||
114 | { | ||
115 | int i; | ||
116 | int complement = 0; | ||
117 | |||
118 | |||
119 | /* zero the bitmap */ | ||
120 | for (i = 0; bmap && i < 32; i++) | ||
121 | { | ||
122 | bmap[i] = 0; | ||
123 | } | ||
124 | |||
125 | /* see if we're going to complement this class */ | ||
126 | if (*text == '^') | ||
127 | { | ||
128 | text++; | ||
129 | complement = 1; | ||
130 | } | ||
131 | |||
132 | /* add in the characters */ | ||
133 | while (*text && *text != ']') | ||
134 | { | ||
135 | /* is this a span of characters? */ | ||
136 | if (text[1] == '-' && text[2]) | ||
137 | { | ||
138 | /* spans can't be backwards */ | ||
139 | if (text[0] > text[2]) | ||
140 | { | ||
141 | FAIL("Backwards span in []"); | ||
142 | } | ||
143 | |||
144 | /* add each character in the span to the bitmap */ | ||
145 | for (i = text[0]; bmap && i <= text[2]; i++) | ||
146 | { | ||
147 | bmap[i >> 3] |= (1 << (i & 7)); | ||
148 | } | ||
149 | |||
150 | /* move past this span */ | ||
151 | text += 3; | ||
152 | } | ||
153 | else | ||
154 | { | ||
155 | /* add this single character to the span */ | ||
156 | i = *text++; | ||
157 | if (bmap) | ||
158 | { | ||
159 | bmap[i >> 3] |= (1 << (i & 7)); | ||
160 | } | ||
161 | } | ||
162 | } | ||
163 | |||
164 | /* make sure the closing ] is missing */ | ||
165 | if (*text++ != ']') | ||
166 | { | ||
167 | FAIL("] missing"); | ||
168 | } | ||
169 | |||
170 | /* if we're supposed to complement this class, then do so */ | ||
171 | if (complement && bmap) | ||
172 | { | ||
173 | for (i = 0; i < 32; i++) | ||
174 | { | ||
175 | bmap[i] = ~bmap[i]; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | return text; | ||
180 | } | ||
181 | |||
182 | |||
183 | |||
184 | |||
185 | /* This function gets the next character or meta character from a string. | ||
186 | * The pointer is incremented by 1, or by 2 for \-quoted characters. For [], | ||
187 | * a bitmap is generated via makeclass() (if re is given), and the | ||
188 | * character-class text is skipped. | ||
189 | */ | ||
190 | static int gettoken(sptr, re) | ||
191 | char **sptr; | ||
192 | regexp *re; | ||
193 | { | ||
194 | int c; | ||
195 | |||
196 | c = **sptr; | ||
197 | ++*sptr; | ||
198 | if (c == '\\') | ||
199 | { | ||
200 | c = **sptr; | ||
201 | ++*sptr; | ||
202 | switch (c) | ||
203 | { | ||
204 | case '<': | ||
205 | return M_BEGWORD; | ||
206 | |||
207 | case '>': | ||
208 | return M_ENDWORD; | ||
209 | |||
210 | case '(': | ||
211 | if (start_cnt >= NSUBEXP) | ||
212 | { | ||
213 | FAIL("Too many \\(s"); | ||
214 | } | ||
215 | end_stk[end_sp++] = start_cnt; | ||
216 | return M_START(start_cnt++); | ||
217 | |||
218 | case ')': | ||
219 | if (end_sp <= 0) | ||
220 | { | ||
221 | FAIL("Mismatched \\)"); | ||
222 | } | ||
223 | return M_END(end_stk[--end_sp]); | ||
224 | |||
225 | case '*': | ||
226 | return M_SPLAT; | ||
227 | |||
228 | case '.': | ||
229 | return M_ANY; | ||
230 | |||
231 | case '+': | ||
232 | return M_PLUS; | ||
233 | |||
234 | case '?': | ||
235 | return M_QMARK; | ||
236 | |||
237 | default: | ||
238 | return c; | ||
239 | } | ||
240 | } | ||
241 | else { | ||
242 | switch (c) | ||
243 | { | ||
244 | case '^': | ||
245 | if (*sptr == retext + 1) | ||
246 | { | ||
247 | return M_BEGLINE; | ||
248 | } | ||
249 | return c; | ||
250 | |||
251 | case '$': | ||
252 | if (!**sptr) | ||
253 | { | ||
254 | return M_ENDLINE; | ||
255 | } | ||
256 | return c; | ||
257 | |||
258 | case '.': | ||
259 | return M_ANY; | ||
260 | |||
261 | case '*': | ||
262 | return M_SPLAT; | ||
263 | |||
264 | case '[': | ||
265 | /* make sure we don't have too many classes */ | ||
266 | if (class_cnt >= 10) | ||
267 | { | ||
268 | FAIL("Too many []s"); | ||
269 | } | ||
270 | |||
271 | /* process the character list for this class */ | ||
272 | if (re) | ||
273 | { | ||
274 | /* generate the bitmap for this class */ | ||
275 | *sptr = makeclass(*sptr, re->program + 1 + 32 * class_cnt); | ||
276 | } | ||
277 | else | ||
278 | { | ||
279 | /* skip to end of the class */ | ||
280 | *sptr = makeclass(*sptr, (char *)0); | ||
281 | } | ||
282 | return M_CLASS(class_cnt++); | ||
283 | |||
284 | default: | ||
285 | return c; | ||
286 | } | ||
287 | } | ||
288 | /*NOTREACHED*/ | ||
289 | } | ||
290 | |||
291 | |||
292 | |||
293 | |||
294 | /* This function calculates the number of bytes that will be needed for a | ||
295 | * compiled RE. Its argument is the uncompiled version. It is not clever | ||
296 | * about catching syntax errors; that is done in a later pass. | ||
297 | */ | ||
298 | static unsigned calcsize(text) | ||
299 | char *text; | ||
300 | { | ||
301 | unsigned size; | ||
302 | int token; | ||
303 | |||
304 | retext = text; | ||
305 | class_cnt = 0; | ||
306 | start_cnt = 1; | ||
307 | end_sp = 0; | ||
308 | size = 5; | ||
309 | while ((token = gettoken(&text, (regexp *)0)) != 0) | ||
310 | { | ||
311 | if (IS_CLASS(token)) | ||
312 | { | ||
313 | size += 34; | ||
314 | } | ||
315 | else if (IS_META(token)) | ||
316 | { | ||
317 | size += 2; | ||
318 | } | ||
319 | else | ||
320 | { | ||
321 | size++; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | return size; | ||
326 | } | ||
327 | |||
328 | |||
329 | |||
330 | /*---------------------------------------------------------------------------*/ | ||
331 | |||
332 | |||
333 | /* This function checks for a match between a character and a token which is | ||
334 | * known to represent a single character. It returns 0 if they match, or | ||
335 | * 1 if they don't. | ||
336 | */ | ||
337 | static int match1(regexp* re, char ch, int token, int ignoreCase) | ||
338 | { | ||
339 | if (!ch) | ||
340 | { | ||
341 | /* the end of a line can't match any RE of width 1 */ | ||
342 | return 1; | ||
343 | } | ||
344 | if (token == M_ANY) | ||
345 | { | ||
346 | return 0; | ||
347 | } | ||
348 | else if (IS_CLASS(token)) | ||
349 | { | ||
350 | if (re->program[1 + 32 * (token - M_CLASS(0)) + (ch >> 3)] & (1 << (ch & 7))) | ||
351 | return 0; | ||
352 | } | ||
353 | else if (ch == token | ||
354 | || (ignoreCase==TRUE && isupper(ch) && tolower(ch) == token)) | ||
355 | { | ||
356 | return 0; | ||
357 | } | ||
358 | return 1; | ||
359 | } | ||
360 | |||
361 | |||
362 | |||
363 | /* This function checks characters up to and including the next closure, at | ||
364 | * which point it does a recursive call to check the rest of it. This function | ||
365 | * returns 0 if everything matches, or 1 if something doesn't match. | ||
366 | */ | ||
367 | /* re -- the regular expression */ | ||
368 | /* str -- the string */ | ||
369 | /* prog -- a portion of re->program, an compiled RE */ | ||
370 | /* here -- a portion of str, the string to compare it to */ | ||
371 | static int match(regexp* re, char* str, char* prog, char* here, int ignoreCase) | ||
372 | { | ||
373 | int token; | ||
374 | int nmatched; | ||
375 | int closure; | ||
376 | |||
377 | for (token = GET_META(prog); !IS_CLOSURE(token); prog++, token = GET_META(prog)) | ||
378 | { | ||
379 | switch (token) | ||
380 | { | ||
381 | /*case M_BEGLINE: can't happen; re->bol is used instead */ | ||
382 | case M_ENDLINE: | ||
383 | if (*here) | ||
384 | return 1; | ||
385 | break; | ||
386 | |||
387 | case M_BEGWORD: | ||
388 | if (here != str && | ||
389 | (here[-1] == '_' || | ||
390 | (isascii(here[-1]) && isalnum(here[-1])))) | ||
391 | return 1; | ||
392 | break; | ||
393 | |||
394 | case M_ENDWORD: | ||
395 | if ((here[0] == '_' || isascii(here[0])) && isalnum(here[0])) | ||
396 | return 1; | ||
397 | break; | ||
398 | |||
399 | case M_START(0): | ||
400 | case M_START(1): | ||
401 | case M_START(2): | ||
402 | case M_START(3): | ||
403 | case M_START(4): | ||
404 | case M_START(5): | ||
405 | case M_START(6): | ||
406 | case M_START(7): | ||
407 | case M_START(8): | ||
408 | case M_START(9): | ||
409 | re->startp[token - M_START(0)] = (char *)here; | ||
410 | break; | ||
411 | |||
412 | case M_END(0): | ||
413 | case M_END(1): | ||
414 | case M_END(2): | ||
415 | case M_END(3): | ||
416 | case M_END(4): | ||
417 | case M_END(5): | ||
418 | case M_END(6): | ||
419 | case M_END(7): | ||
420 | case M_END(8): | ||
421 | case M_END(9): | ||
422 | re->endp[token - M_END(0)] = (char *)here; | ||
423 | if (token == M_END(0)) | ||
424 | { | ||
425 | return 0; | ||
426 | } | ||
427 | break; | ||
428 | |||
429 | default: /* literal, M_CLASS(n), or M_ANY */ | ||
430 | if (match1(re, *here, token, ignoreCase) != 0) | ||
431 | return 1; | ||
432 | here++; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | /* C L O S U R E */ | ||
437 | |||
438 | /* step 1: see what we have to match against, and move "prog" to point | ||
439 | * the the remainder of the compiled RE. | ||
440 | */ | ||
441 | closure = token; | ||
442 | prog++, token = GET_META(prog); | ||
443 | prog++; | ||
444 | |||
445 | /* step 2: see how many times we can match that token against the string */ | ||
446 | for (nmatched = 0; | ||
447 | (closure != M_QMARK || nmatched < 1) && *here && match1(re, *here, token, ignoreCase) == 0; | ||
448 | nmatched++, here++) | ||
449 | { | ||
450 | } | ||
451 | |||
452 | /* step 3: try to match the remainder, and back off if it doesn't */ | ||
453 | while (nmatched >= 0 && match(re, str, prog, here, ignoreCase) != 0) | ||
454 | { | ||
455 | nmatched--; | ||
456 | here--; | ||
457 | } | ||
458 | |||
459 | /* so how did it work out? */ | ||
460 | if (nmatched >= ((closure == M_PLUS) ? 1 : 0)) | ||
461 | return 0; | ||
462 | return 1; | ||
463 | } | ||
464 | |||
465 | |||
466 | /* This function compiles a regexp. */ | ||
467 | extern regexp *regcomp(char* text) | ||
468 | { | ||
469 | int needfirst; | ||
470 | unsigned size; | ||
471 | int token; | ||
472 | int peek; | ||
473 | char *build; | ||
474 | regexp *re; | ||
475 | |||
476 | |||
477 | /* prepare for error handling */ | ||
478 | re = (regexp *)0; | ||
479 | if (setjmp(errorhandler)) | ||
480 | { | ||
481 | if (re) | ||
482 | { | ||
483 | free(re); | ||
484 | } | ||
485 | return (regexp *)0; | ||
486 | } | ||
487 | |||
488 | /* if an empty regexp string was given, use the previous one */ | ||
489 | if (*text == 0) | ||
490 | { | ||
491 | if (!previous) | ||
492 | { | ||
493 | FAIL("No previous RE"); | ||
494 | } | ||
495 | text = previous; | ||
496 | } | ||
497 | else /* non-empty regexp given, so remember it */ | ||
498 | { | ||
499 | if (previous) | ||
500 | free(previous); | ||
501 | previous = (char *)malloc((unsigned)(strlen(text) + 1)); | ||
502 | if (previous) | ||
503 | strcpy(previous, text); | ||
504 | } | ||
505 | |||
506 | /* allocate memory */ | ||
507 | class_cnt = 0; | ||
508 | start_cnt = 1; | ||
509 | end_sp = 0; | ||
510 | retext = text; | ||
511 | size = calcsize(text) + sizeof(regexp); | ||
512 | re = (regexp *)malloc((unsigned)size); | ||
513 | |||
514 | if (!re) | ||
515 | { | ||
516 | FAIL("Not enough memory for this RE"); | ||
517 | } | ||
518 | |||
519 | /* compile it */ | ||
520 | build = &re->program[1 + 32 * class_cnt]; | ||
521 | re->program[0] = class_cnt; | ||
522 | for (token = 0; token < NSUBEXP; token++) | ||
523 | { | ||
524 | re->startp[token] = re->endp[token] = (char *)0; | ||
525 | } | ||
526 | re->first = 0; | ||
527 | re->bol = 0; | ||
528 | re->minlen = 0; | ||
529 | needfirst = 1; | ||
530 | class_cnt = 0; | ||
531 | start_cnt = 1; | ||
532 | end_sp = 0; | ||
533 | retext = text; | ||
534 | for (token = M_START(0), peek = gettoken(&text, re); | ||
535 | token; | ||
536 | token = peek, peek = gettoken(&text, re)) | ||
537 | { | ||
538 | /* special processing for the closure operator */ | ||
539 | if (IS_CLOSURE(peek)) | ||
540 | { | ||
541 | /* detect misuse of closure operator */ | ||
542 | if (IS_START(token)) | ||
543 | { | ||
544 | FAIL("* or \\+ or \\? follows nothing"); | ||
545 | } | ||
546 | else if (IS_META(token) && token != M_ANY && !IS_CLASS(token)) | ||
547 | { | ||
548 | FAIL("* or \\+ or \\? can only follow a normal character or . or []"); | ||
549 | } | ||
550 | |||
551 | /* it is okay -- make it prefix instead of postfix */ | ||
552 | ADD_META(build, peek); | ||
553 | |||
554 | /* take care of "needfirst" - is this the first char? */ | ||
555 | if (needfirst && peek == M_PLUS && !IS_META(token)) | ||
556 | { | ||
557 | re->first = token; | ||
558 | } | ||
559 | needfirst = 0; | ||
560 | |||
561 | /* we used "peek" -- need to refill it */ | ||
562 | peek = gettoken(&text, re); | ||
563 | if (IS_CLOSURE(peek)) | ||
564 | { | ||
565 | FAIL("* or \\+ or \\? doubled up"); | ||
566 | } | ||
567 | } | ||
568 | else if (!IS_META(token)) | ||
569 | { | ||
570 | /* normal char is NOT argument of closure */ | ||
571 | if (needfirst) | ||
572 | { | ||
573 | re->first = token; | ||
574 | needfirst = 0; | ||
575 | } | ||
576 | re->minlen++; | ||
577 | } | ||
578 | else if (token == M_ANY || IS_CLASS(token)) | ||
579 | { | ||
580 | /* . or [] is NOT argument of closure */ | ||
581 | needfirst = 0; | ||
582 | re->minlen++; | ||
583 | } | ||
584 | |||
585 | /* the "token" character is not closure -- process it normally */ | ||
586 | if (token == M_BEGLINE) | ||
587 | { | ||
588 | /* set the BOL flag instead of storing M_BEGLINE */ | ||
589 | re->bol = 1; | ||
590 | } | ||
591 | else if (IS_META(token)) | ||
592 | { | ||
593 | ADD_META(build, token); | ||
594 | } | ||
595 | else | ||
596 | { | ||
597 | *build++ = token; | ||
598 | } | ||
599 | } | ||
600 | |||
601 | /* end it with a \) which MUST MATCH the opening \( */ | ||
602 | ADD_META(build, M_END(0)); | ||
603 | if (end_sp > 0) | ||
604 | { | ||
605 | FAIL("Not enough \\)s"); | ||
606 | } | ||
607 | |||
608 | return re; | ||
609 | } | ||
610 | |||
611 | |||
612 | |||
613 | |||
614 | /* This function searches through a string for text that matches an RE. */ | ||
615 | /* re -- the compiled regexp to search for */ | ||
616 | /* str -- the string to search through */ | ||
617 | /* bol -- does str start at the beginning of a line? (boolean) */ | ||
618 | /* ignoreCase -- ignoreCase or not */ | ||
619 | extern int regexec(struct regexp* re, char* str, int bol, int ignoreCase) | ||
620 | { | ||
621 | char *prog; /* the entry point of re->program */ | ||
622 | int len; /* length of the string */ | ||
623 | char *here; | ||
624 | |||
625 | /* if must start at the beginning of a line, and this isn't, then fail */ | ||
626 | if (re->bol && bol==TRUE) | ||
627 | { | ||
628 | return FALSE; | ||
629 | } | ||
630 | |||
631 | len = strlen(str); | ||
632 | prog = re->program + 1 + 32 * re->program[0]; | ||
633 | |||
634 | /* search for the RE in the string */ | ||
635 | if (re->bol) | ||
636 | { | ||
637 | /* must occur at BOL */ | ||
638 | if ((re->first | ||
639 | && match1(re, *(char *)str, re->first, ignoreCase))/* wrong first letter? */ | ||
640 | || len < re->minlen /* not long enough? */ | ||
641 | || match(re, (char *)str, prog, str, ignoreCase)) /* doesn't match? */ | ||
642 | return FALSE; /* THEN FAIL! */ | ||
643 | } | ||
644 | else if (ignoreCase == FALSE) | ||
645 | { | ||
646 | /* can occur anywhere in the line, noignorecase */ | ||
647 | for (here = (char *)str; | ||
648 | (re->first && re->first != *here) | ||
649 | || match(re, (char *)str, prog, here, ignoreCase); | ||
650 | here++, len--) | ||
651 | { | ||
652 | if (len < re->minlen) | ||
653 | return FALSE; | ||
654 | } | ||
655 | } | ||
656 | else | ||
657 | { | ||
658 | /* can occur anywhere in the line, ignorecase */ | ||
659 | for (here = (char *)str; | ||
660 | (re->first && match1(re, *here, (int)re->first, ignoreCase)) | ||
661 | || match(re, (char *)str, prog, here, ignoreCase); | ||
662 | here++, len--) | ||
663 | { | ||
664 | if (len < re->minlen) | ||
665 | return FALSE; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | /* if we didn't fail, then we must have succeeded */ | ||
670 | return TRUE; | ||
671 | } | ||
672 | |||
673 | |||
674 | |||
675 | |||
676 | |||
677 | /* This performs substitutions after a regexp match has been found. */ | ||
678 | extern void regsub(regexp* re, char* src, char* dst) | ||
679 | { | ||
680 | char *cpy; | ||
681 | char *end; | ||
682 | char c; | ||
683 | char *start; | ||
684 | int mod; | ||
685 | |||
686 | mod = 0; | ||
687 | |||
688 | start = src; | ||
689 | while ((c = *src++) != '\0') | ||
690 | { | ||
691 | /* recognize any meta characters */ | ||
692 | if (c == '&') | ||
693 | { | ||
694 | cpy = re->startp[0]; | ||
695 | end = re->endp[0]; | ||
696 | } | ||
697 | else if (c == '~') | ||
698 | { | ||
699 | cpy = previous1; | ||
700 | if (cpy) | ||
701 | end = cpy + strlen(cpy); | ||
702 | } | ||
703 | else | ||
704 | if (c == '\\') | ||
705 | { | ||
706 | c = *src++; | ||
707 | switch (c) | ||
708 | { | ||
709 | case '0': | ||
710 | case '1': | ||
711 | case '2': | ||
712 | case '3': | ||
713 | case '4': | ||
714 | case '5': | ||
715 | case '6': | ||
716 | case '7': | ||
717 | case '8': | ||
718 | case '9': | ||
719 | /* \0 thru \9 mean "copy subexpression" */ | ||
720 | c -= '0'; | ||
721 | cpy = re->startp[(int)c]; | ||
722 | end = re->endp[(int)c]; | ||
723 | break; | ||
724 | case 'U': | ||
725 | case 'u': | ||
726 | case 'L': | ||
727 | case 'l': | ||
728 | /* \U and \L mean "convert to upper/lowercase" */ | ||
729 | mod = c; | ||
730 | continue; | ||
731 | |||
732 | case 'E': | ||
733 | case 'e': | ||
734 | /* \E ends the \U or \L */ | ||
735 | mod = 0; | ||
736 | continue; | ||
737 | case '&': | ||
738 | /* "\&" means "original text" */ | ||
739 | *dst++ = c; | ||
740 | continue; | ||
741 | |||
742 | case '~': | ||
743 | /* "\~" means "previous text, if any" */ | ||
744 | *dst++ = c; | ||
745 | continue; | ||
746 | default: | ||
747 | /* ordinary char preceded by backslash */ | ||
748 | *dst++ = c; | ||
749 | continue; | ||
750 | } | ||
751 | } | ||
752 | else | ||
753 | { | ||
754 | /* ordinary character, so just copy it */ | ||
755 | *dst++ = c; | ||
756 | continue; | ||
757 | } | ||
758 | |||
759 | /* Note: to reach this point in the code, we must have evaded | ||
760 | * all "continue" statements. To do that, we must have hit | ||
761 | * a metacharacter that involves copying. | ||
762 | */ | ||
763 | |||
764 | /* if there is nothing to copy, loop */ | ||
765 | if (!cpy) | ||
766 | continue; | ||
767 | |||
768 | /* copy over a portion of the original */ | ||
769 | while (cpy < end) | ||
770 | { | ||
771 | switch (mod) | ||
772 | { | ||
773 | case 'U': | ||
774 | case 'u': | ||
775 | /* convert to uppercase */ | ||
776 | if (isascii(*cpy) && islower(*cpy)) | ||
777 | { | ||
778 | *dst++ = toupper(*cpy); | ||
779 | cpy++; | ||
780 | } | ||
781 | else | ||
782 | { | ||
783 | *dst++ = *cpy++; | ||
784 | } | ||
785 | break; | ||
786 | |||
787 | case 'L': | ||
788 | case 'l': | ||
789 | /* convert to lowercase */ | ||
790 | if (isascii(*cpy) && isupper(*cpy)) | ||
791 | { | ||
792 | *dst++ = tolower(*cpy); | ||
793 | cpy++; | ||
794 | } | ||
795 | else | ||
796 | { | ||
797 | *dst++ = *cpy++; | ||
798 | } | ||
799 | break; | ||
800 | |||
801 | default: | ||
802 | /* copy without any conversion */ | ||
803 | *dst++ = *cpy++; | ||
804 | } | ||
805 | |||
806 | /* \u and \l end automatically after the first char */ | ||
807 | if (mod && (mod == 'u' || mod == 'l')) | ||
808 | { | ||
809 | mod = 0; | ||
810 | } | ||
811 | } | ||
812 | } | ||
813 | *dst = '\0'; | ||
814 | |||
815 | /* remember what text we inserted this time */ | ||
816 | if (previous1) | ||
817 | free(previous1); | ||
818 | previous1 = (char *)malloc((unsigned)(strlen(start) + 1)); | ||
819 | if (previous1) | ||
820 | strcpy(previous1, start); | ||
821 | } | ||
822 | |||
823 | |||
824 | #endif /* BB_REGEXP */ | ||
825 | |||
826 | |||
diff --git a/smtpout b/smtpout deleted file mode 100644 index 635a83c6f..000000000 --- a/smtpout +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | echo '.' >smtpout echo 'QUIT' >smtpout | ||
2 | kjfjkjd | ||
@@ -53,12 +53,17 @@ volatile void usage(const char *usage) | |||
53 | int | 53 | int |
54 | get_kernel_revision() | 54 | get_kernel_revision() |
55 | { | 55 | { |
56 | FILE *f; | 56 | FILE *file; |
57 | int major=0, minor=0, patch=0; | 57 | int major=0, minor=0, patch=0; |
58 | 58 | char* filename="/proc/sys/kernel/osrelease"; | |
59 | f = fopen("/proc/sys/kernel/osrelease","r"); | 59 | |
60 | fscanf(f,"%d.%d.%d",&major,&minor,&patch); | 60 | file = fopen(filename,"r"); |
61 | fclose(f); | 61 | if (file == NULL) { |
62 | perror(filename); | ||
63 | return( 0); | ||
64 | } | ||
65 | fscanf(file,"%d.%d.%d",&major,&minor,&patch); | ||
66 | fclose(file); | ||
62 | return major*65536 + minor*256 + patch; | 67 | return major*65536 + minor*256 + patch; |
63 | } | 68 | } |
64 | 69 | ||
@@ -312,94 +317,6 @@ const char *timeString(time_t timeVal) | |||
312 | 317 | ||
313 | 318 | ||
314 | /* | 319 | /* |
315 | * Routine to see if a text string is matched by a wildcard pattern. | ||
316 | * Returns TRUE if the text is matched, or FALSE if it is not matched | ||
317 | * or if the pattern is invalid. | ||
318 | * * matches zero or more characters | ||
319 | * ? matches a single character | ||
320 | * [abc] matches 'a', 'b' or 'c' | ||
321 | * \c quotes character c | ||
322 | * Adapted from code written by Ingo Wilken. | ||
323 | */ | ||
324 | int match(const char *text, const char *pattern) | ||
325 | { | ||
326 | const char *retryPat; | ||
327 | const char *retryText; | ||
328 | int ch; | ||
329 | int found; | ||
330 | |||
331 | retryPat = NULL; | ||
332 | retryText = NULL; | ||
333 | |||
334 | while (*text || *pattern) { | ||
335 | ch = *pattern++; | ||
336 | |||
337 | switch (ch) { | ||
338 | case '*': | ||
339 | retryPat = pattern; | ||
340 | retryText = text; | ||
341 | break; | ||
342 | |||
343 | case '[': | ||
344 | found = FALSE; | ||
345 | |||
346 | while ((ch = *pattern++) != ']') { | ||
347 | if (ch == '\\') | ||
348 | ch = *pattern++; | ||
349 | |||
350 | if (ch == '\0') | ||
351 | return FALSE; | ||
352 | |||
353 | if (*text == ch) | ||
354 | found = TRUE; | ||
355 | } | ||
356 | |||
357 | if (!found) { | ||
358 | pattern = retryPat; | ||
359 | text = ++retryText; | ||
360 | } | ||
361 | |||
362 | /* fall into next case */ | ||
363 | |||
364 | case '?': | ||
365 | if (*text++ == '\0') | ||
366 | return FALSE; | ||
367 | |||
368 | break; | ||
369 | |||
370 | case '\\': | ||
371 | ch = *pattern++; | ||
372 | |||
373 | if (ch == '\0') | ||
374 | return FALSE; | ||
375 | |||
376 | /* fall into next case */ | ||
377 | |||
378 | default: | ||
379 | if (*text == ch) { | ||
380 | if (*text) | ||
381 | text++; | ||
382 | break; | ||
383 | } | ||
384 | |||
385 | if (*text) { | ||
386 | pattern = retryPat; | ||
387 | text = ++retryText; | ||
388 | break; | ||
389 | } | ||
390 | |||
391 | return FALSE; | ||
392 | } | ||
393 | |||
394 | if (pattern == NULL) | ||
395 | return FALSE; | ||
396 | } | ||
397 | |||
398 | return TRUE; | ||
399 | } | ||
400 | |||
401 | |||
402 | /* | ||
403 | * Write all of the supplied buffer out to a file. | 320 | * Write all of the supplied buffer out to a file. |
404 | * This does multiple writes as necessary. | 321 | * This does multiple writes as necessary. |
405 | * Returns the amount written, or -1 on an error. | 322 | * Returns the amount written, or -1 on an error. |
@@ -695,13 +612,17 @@ parse_mode( const char* s, mode_t* theMode) | |||
695 | uid_t | 612 | uid_t |
696 | my_getid(const char *filename, char *name, uid_t id) | 613 | my_getid(const char *filename, char *name, uid_t id) |
697 | { | 614 | { |
698 | FILE *stream; | 615 | FILE *file; |
699 | char *rname, *start, *end, buf[128]; | 616 | char *rname, *start, *end, buf[128]; |
700 | uid_t rid; | 617 | uid_t rid; |
701 | 618 | ||
702 | stream=fopen(filename,"r"); | 619 | file=fopen(filename,"r"); |
620 | if (file == NULL) { | ||
621 | perror(filename); | ||
622 | return (-1); | ||
623 | } | ||
703 | 624 | ||
704 | while (fgets (buf, 128, stream) != NULL) { | 625 | while (fgets (buf, 128, file) != NULL) { |
705 | if (buf[0] == '#') | 626 | if (buf[0] == '#') |
706 | continue; | 627 | continue; |
707 | 628 | ||
@@ -731,7 +652,7 @@ my_getid(const char *filename, char *name, uid_t id) | |||
731 | return( TRUE); | 652 | return( TRUE); |
732 | } | 653 | } |
733 | } | 654 | } |
734 | fclose(stream); | 655 | fclose(file); |
735 | return (-1); | 656 | return (-1); |
736 | } | 657 | } |
737 | 658 | ||
@@ -763,4 +684,40 @@ my_getgrgid(char* group, gid_t gid) | |||
763 | #endif | 684 | #endif |
764 | 685 | ||
765 | 686 | ||
687 | |||
688 | #if !defined BB_REGEXP && (defined BB_GREP || defined BB_FIND ) | ||
689 | /* This tries to find a needle in a haystack, but does so by | ||
690 | * only trying to match literal strings (look 'ma, no regexps!) | ||
691 | * This is short, sweet, and carries _very_ little baggage, | ||
692 | * unlike its beefier cousin a few lines down... | ||
693 | * -Erik Andersen | ||
694 | */ | ||
695 | extern int find_match(char *haystack, char *needle, int ignoreCase) | ||
696 | { | ||
697 | |||
698 | if (ignoreCase == FALSE) { | ||
699 | haystack = strstr (haystack, needle); | ||
700 | if (haystack == NULL) | ||
701 | return FALSE; | ||
702 | return TRUE; | ||
703 | } else { | ||
704 | int i; | ||
705 | char needle1[BUF_SIZE]; | ||
706 | char haystack1[BUF_SIZE]; | ||
707 | |||
708 | strncpy( haystack1, haystack, sizeof(haystack1)); | ||
709 | strncpy( needle1, needle, sizeof(needle1)); | ||
710 | for( i=0; i<sizeof(haystack1) && haystack1[i]; i++) | ||
711 | haystack1[i]=tolower( haystack1[i]); | ||
712 | for( i=0; i<sizeof(needle1) && needle1[i]; i++) | ||
713 | needle1[i]=tolower( needle1[i]); | ||
714 | haystack = strstr (haystack1, needle1); | ||
715 | if (haystack == NULL) | ||
716 | return FALSE; | ||
717 | return TRUE; | ||
718 | } | ||
719 | } | ||
720 | #endif | ||
721 | |||
766 | /* END CODE */ | 722 | /* END CODE */ |
723 | |||