blob: 3779e5510a9eda7ea7ae988f140bfc40b003e63c [file] [log] [blame]
Eric Andersencc8ed391999-10-05 16:24:54 +00001/*
2 * Copyright (c) 1999 by David I. Bell
3 * Permission is granted to use, distribute, or modify this source,
4 * provided that this copyright notice remains intact.
5 *
6 * The "grep" command, taken from sash.
7 * This provides basic file searching.
8 *
9 * Permission to distribute this code under the GPL has been granted.
10 * Modified for busybox by Erik Andersen <andersee@debian.org> <andersen@lineo.com>
11 */
12
13#include "internal.h"
14#ifdef BB_GREP
15
16#include <stdio.h>
17#include <dirent.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <signal.h>
21#include <time.h>
22#include <ctype.h>
23
24
25const char grep_usage[] =
26"Search the input file(s) for lines matching the given pattern.\n"
27"\tI search stdin if no files are given.\n"
28"\tI can't grok full regular expressions.\n"
29"usage: grep [in] PATTERN [FILES]...\n"
30"\ti=ignore case, n=list line numbers\n";
31
32
33
34static BOOL search
35 (const char * string, const char * word, BOOL ignoreCase);
36
37
38extern int
39grep_main(struct FileInfo * unused, int argc, char ** argv)
40{
41 FILE * fp;
42 const char * word;
43 const char * name;
44 const char * cp;
45 BOOL tellName;
46 BOOL ignoreCase;
47 BOOL tellLine;
48 long line;
49 char buf[BUF_SIZE];
50
51 ignoreCase = FALSE;
52 tellLine = FALSE;
53
54 argc--;
55 argv++;
56 if (argc < 1)
57 {
58 fprintf(stderr, "%s", grep_usage);
59 return 1;
60 }
61
62 if (**argv == '-')
63 {
64 argc--;
65 cp = *argv++;
66
67 while (*++cp) switch (*cp)
68 {
69 case 'i':
70 ignoreCase = TRUE;
71 break;
72
73 case 'n':
74 tellLine = TRUE;
75 break;
76
77 default:
78 fprintf(stderr, "Unknown option\n");
79 return 1;
80 }
81 }
82
83 word = *argv++;
84 argc--;
85
86 tellName = (argc > 1);
87
88 while (argc-- > 0)
89 {
90 name = *argv++;
91
92 fp = fopen(name, "r");
93
94 if (fp == NULL)
95 {
96 perror(name);
97
98 continue;
99 }
100
101 line = 0;
102
103 while (fgets(buf, sizeof(buf), fp))
104 {
105 line++;
106
107 cp = &buf[strlen(buf) - 1];
108
109 if (*cp != '\n')
110 fprintf(stderr, "%s: Line too long\n", name);
111
112 if (search(buf, word, ignoreCase))
113 {
114 if (tellName)
115 printf("%s: ", name);
116
117 if (tellLine)
118 printf("%ld: ", line);
119
120 fputs(buf, stdout);
121 }
122 }
123
124 if (ferror(fp))
125 perror(name);
126
127 fclose(fp);
128 }
129 return 0;
130}
131
132
133/*
134 * See if the specified word is found in the specified string.
135 */
136static BOOL
137search(const char * string, const char * word, BOOL ignoreCase)
138{
139 const char * cp1;
140 const char * cp2;
141 int len;
142 int lowFirst;
143 int ch1;
144 int ch2;
145
146 len = strlen(word);
147
148 if (!ignoreCase)
149 {
150 while (TRUE)
151 {
152 string = strchr(string, word[0]);
153
154 if (string == NULL)
155 return FALSE;
156
157 if (memcmp(string, word, len) == 0)
158 return TRUE;
159
160 string++;
161 }
162 }
163
164 /*
165 * Here if we need to check case independence.
166 * Do the search by lower casing both strings.
167 */
168 lowFirst = *word;
169
170 if (isupper(lowFirst))
171 lowFirst = tolower(lowFirst);
172
173 while (TRUE)
174 {
175 while (*string && (*string != lowFirst) &&
176 (!isupper(*string) || (tolower(*string) != lowFirst)))
177 {
178 string++;
179 }
180
181 if (*string == '\0')
182 return FALSE;
183
184 cp1 = string;
185 cp2 = word;
186
187 do
188 {
189 if (*cp2 == '\0')
190 return TRUE;
191
192 ch1 = *cp1++;
193
194 if (isupper(ch1))
195 ch1 = tolower(ch1);
196
197 ch2 = *cp2++;
198
199 if (isupper(ch2))
200 ch2 = tolower(ch2);
201
202 }
203 while (ch1 == ch2);
204
205 string++;
206 }
207}
208
209#endif
210/* END CODE */