More stuff.
[oweals/busybox.git] / 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 int search (const char *string, const char *word, int ignoreCase);
35
36
37 extern int grep_main (int argc, char **argv)
38 {
39     FILE *fp;
40     const char *word;
41     const char *name;
42     const char *cp;
43     int tellName;
44     int ignoreCase;
45     int tellLine;
46     long line;
47     char buf[BUF_SIZE];
48
49     ignoreCase = FALSE;
50     tellLine = FALSE;
51
52     argc--;
53     argv++;
54     if (argc < 1) {
55         fprintf (stderr, "%s", grep_usage);
56         return 1;
57     }
58
59     if (**argv == '-') {
60         argc--;
61         cp = *argv++;
62
63         while (*++cp)
64             switch (*cp) {
65             case 'i':
66                 ignoreCase = TRUE;
67                 break;
68
69             case 'n':
70                 tellLine = TRUE;
71                 break;
72
73             default:
74                 fprintf (stderr, "Unknown option\n");
75                 return 1;
76             }
77     }
78
79     word = *argv++;
80     argc--;
81
82     tellName = (argc > 1);
83
84     while (argc-- > 0) {
85         name = *argv++;
86
87         fp = fopen (name, "r");
88
89         if (fp == NULL) {
90             perror (name);
91
92             continue;
93         }
94
95         line = 0;
96
97         while (fgets (buf, sizeof (buf), fp)) {
98             line++;
99
100             cp = &buf[strlen (buf) - 1];
101
102             if (*cp != '\n')
103                 fprintf (stderr, "%s: Line too long\n", name);
104
105             if (search (buf, word, ignoreCase)) {
106                 if (tellName)
107                     printf ("%s: ", name);
108
109                 if (tellLine)
110                     printf ("%ld: ", line);
111
112                 fputs (buf, stdout);
113             }
114         }
115
116         if (ferror (fp))
117             perror (name);
118
119         fclose (fp);
120     }
121     return 0;
122 }
123
124
125 /*
126  * See if the specified word is found in the specified string.
127  */
128 static int search (const char *string, const char *word, int ignoreCase)
129 {
130     const char *cp1;
131     const char *cp2;
132     int len;
133     int lowFirst;
134     int ch1;
135     int ch2;
136
137     len = strlen (word);
138
139     if (!ignoreCase) {
140         while (TRUE) {
141             string = strchr (string, word[0]);
142
143             if (string == NULL)
144                 return FALSE;
145
146             if (memcmp (string, word, len) == 0)
147                 return TRUE;
148
149             string++;
150         }
151     }
152
153     /* 
154      * Here if we need to check case independence.
155      * Do the search by lower casing both strings.
156      */
157     lowFirst = *word;
158
159     if (isupper (lowFirst))
160         lowFirst = tolower (lowFirst);
161
162     while (TRUE) {
163         while (*string && (*string != lowFirst) &&
164                (!isupper (*string) || (tolower (*string) != lowFirst))) {
165             string++;
166         }
167
168         if (*string == '\0')
169             return FALSE;
170
171         cp1 = string;
172         cp2 = word;
173
174         do {
175             if (*cp2 == '\0')
176                 return TRUE;
177
178             ch1 = *cp1++;
179
180             if (isupper (ch1))
181                 ch1 = tolower (ch1);
182
183             ch2 = *cp2++;
184
185             if (isupper (ch2))
186                 ch2 = tolower (ch2);
187
188         }
189         while (ch1 == ch2);
190
191         string++;
192     }
193     return (TRUE);
194 }
195
196 #endif
197 /* END CODE */