More stuff.
[oweals/busybox.git] / findutils / grep.c
1 /*
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
25 const 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
34 static  BOOL    search
35         (const char * string, const char * word, BOOL ignoreCase);
36
37
38 extern int 
39 grep_main(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  */
136 static BOOL
137 search(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 */