blob: 11198b851c15daba221c9c5ffc434ab7769c3dae [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[] =
Eric Andersen596e5461999-10-07 08:30:23 +000026 "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";
Eric Andersencc8ed391999-10-05 16:24:54 +000031
32
33
Eric Andersen596e5461999-10-07 08:30:23 +000034static BOOL search (const char *string, const char *word, BOOL ignoreCase);
Eric Andersencc8ed391999-10-05 16:24:54 +000035
36
Eric Andersen596e5461999-10-07 08:30:23 +000037extern int grep_main (int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +000038{
Eric Andersen596e5461999-10-07 08:30:23 +000039 FILE *fp;
40 const char *word;
41 const char *name;
42 const char *cp;
43 BOOL tellName;
44 BOOL ignoreCase;
45 BOOL tellLine;
46 long line;
47 char buf[BUF_SIZE];
Eric Andersencc8ed391999-10-05 16:24:54 +000048
Eric Andersen596e5461999-10-07 08:30:23 +000049 ignoreCase = FALSE;
50 tellLine = FALSE;
Eric Andersencc8ed391999-10-05 16:24:54 +000051
Eric Andersen596e5461999-10-07 08:30:23 +000052 argc--;
53 argv++;
54 if (argc < 1) {
55 fprintf (stderr, "%s", grep_usage);
56 return 1;
57 }
58
59 if (**argv == '-') {
Eric Andersencc8ed391999-10-05 16:24:54 +000060 argc--;
Eric Andersen596e5461999-10-07 08:30:23 +000061 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");
Eric Andersencc8ed391999-10-05 16:24:54 +000075 return 1;
Eric Andersen596e5461999-10-07 08:30:23 +000076 }
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;
Eric Andersencc8ed391999-10-05 16:24:54 +000093 }
94
Eric Andersen596e5461999-10-07 08:30:23 +000095 line = 0;
Eric Andersencc8ed391999-10-05 16:24:54 +000096
Eric Andersen596e5461999-10-07 08:30:23 +000097 while (fgets (buf, sizeof (buf), fp)) {
98 line++;
Eric Andersencc8ed391999-10-05 16:24:54 +000099
Eric Andersen596e5461999-10-07 08:30:23 +0000100 cp = &buf[strlen (buf) - 1];
Eric Andersencc8ed391999-10-05 16:24:54 +0000101
Eric Andersen596e5461999-10-07 08:30:23 +0000102 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 }
Eric Andersencc8ed391999-10-05 16:24:54 +0000114 }
115
Eric Andersen596e5461999-10-07 08:30:23 +0000116 if (ferror (fp))
117 perror (name);
Eric Andersencc8ed391999-10-05 16:24:54 +0000118
Eric Andersen596e5461999-10-07 08:30:23 +0000119 fclose (fp);
120 }
121 return 0;
Eric Andersencc8ed391999-10-05 16:24:54 +0000122}
123
124
125/*
126 * See if the specified word is found in the specified string.
127 */
Eric Andersen596e5461999-10-07 08:30:23 +0000128static BOOL search (const char *string, const char *word, BOOL ignoreCase)
Eric Andersencc8ed391999-10-05 16:24:54 +0000129{
Eric Andersen596e5461999-10-07 08:30:23 +0000130 const char *cp1;
131 const char *cp2;
132 int len;
133 int lowFirst;
134 int ch1;
135 int ch2;
Eric Andersencc8ed391999-10-05 16:24:54 +0000136
Eric Andersen596e5461999-10-07 08:30:23 +0000137 len = strlen (word);
Eric Andersencc8ed391999-10-05 16:24:54 +0000138
Eric Andersen596e5461999-10-07 08:30:23 +0000139 if (!ignoreCase) {
140 while (TRUE) {
141 string = strchr (string, word[0]);
Eric Andersencc8ed391999-10-05 16:24:54 +0000142
Eric Andersen596e5461999-10-07 08:30:23 +0000143 if (string == NULL)
144 return FALSE;
Eric Andersencc8ed391999-10-05 16:24:54 +0000145
Eric Andersen596e5461999-10-07 08:30:23 +0000146 if (memcmp (string, word, len) == 0)
147 return TRUE;
Eric Andersencc8ed391999-10-05 16:24:54 +0000148
Eric Andersen596e5461999-10-07 08:30:23 +0000149 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++;
Eric Andersencc8ed391999-10-05 16:24:54 +0000166 }
167
Eric Andersen596e5461999-10-07 08:30:23 +0000168 if (*string == '\0')
169 return FALSE;
Eric Andersencc8ed391999-10-05 16:24:54 +0000170
Eric Andersen596e5461999-10-07 08:30:23 +0000171 cp1 = string;
172 cp2 = word;
Eric Andersencc8ed391999-10-05 16:24:54 +0000173
Eric Andersen596e5461999-10-07 08:30:23 +0000174 do {
175 if (*cp2 == '\0')
176 return TRUE;
Eric Andersencc8ed391999-10-05 16:24:54 +0000177
Eric Andersen596e5461999-10-07 08:30:23 +0000178 ch1 = *cp1++;
Eric Andersencc8ed391999-10-05 16:24:54 +0000179
Eric Andersen596e5461999-10-07 08:30:23 +0000180 if (isupper (ch1))
181 ch1 = tolower (ch1);
Eric Andersencc8ed391999-10-05 16:24:54 +0000182
Eric Andersen596e5461999-10-07 08:30:23 +0000183 ch2 = *cp2++;
Eric Andersencc8ed391999-10-05 16:24:54 +0000184
Eric Andersen596e5461999-10-07 08:30:23 +0000185 if (isupper (ch2))
186 ch2 = tolower (ch2);
Eric Andersencc8ed391999-10-05 16:24:54 +0000187
Eric Andersencc8ed391999-10-05 16:24:54 +0000188 }
Eric Andersen596e5461999-10-07 08:30:23 +0000189 while (ch1 == ch2);
190
191 string++;
192 }
193 return (TRUE);
Eric Andersencc8ed391999-10-05 16:24:54 +0000194}
195
196#endif
197/* END CODE */