First commit, mainly testing.
[reactos.git] / rosapps / cmdutils / find.c
1 /* find.c */
2
3 /* Copyright (C) 1994-2002, Jim Hall <jhall@freedos.org> */
4
5 /* Adapted for ReactOS */
6
7 /*
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24 /* This program locates a string in a text file and prints those lines
25 * that contain the string. Multiple files are clearly separated.
26 */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include <dir.h>
34 #include <dos.h>
35
36
37 /* Symbol definition */
38 #define MAX_STR 1024
39
40
41 /* This function prints out all lines containing a substring. There are some
42 * conditions that may be passed to the function.
43 *
44 * RETURN: If the string was found at least once, returns 1.
45 * If the string was not found at all, returns 0.
46 */
47 int
48 find_str (char *sz, FILE *p, int invert_search,
49 int count_lines, int number_output, int ignore_case)
50 {
51 int i, length;
52 long line_number = 0, total_lines = 0;
53 char *c, temp_str[MAX_STR], this_line[MAX_STR];
54
55 /* Convert to upper if needed */
56 if (ignore_case)
57 {
58 length = strlen (sz);
59 for (i = 0; i < length; i++)
60 sz[i] = toupper (sz[i]);
61 }
62
63 /* Scan the file until EOF */
64 while (fgets (temp_str, MAX_STR, p) != NULL)
65 {
66 /* Remove the trailing newline */
67 length = strlen (temp_str);
68 if (temp_str[length-1] == '\n')
69 {
70 temp_str[length-1] = '\0';
71 }
72
73 /* Increment number of lines */
74 line_number++;
75 strcpy (this_line, temp_str);
76
77 /* Convert to upper if needed */
78 if (ignore_case)
79 {
80 for (i = 0; i < length; i++)
81 {
82 temp_str[i] = toupper (temp_str[i]);
83 }
84 }
85
86 /* Locate the substring */
87
88 /* strstr() returns a pointer to the first occurrence in the
89 string of the substring */
90 c = strstr (temp_str, sz);
91
92 if ( ((invert_search) ? (c == NULL) : (c != NULL)) )
93 {
94 if (!count_lines)
95 {
96 if (number_output)
97 printf ("%ld:", line_number);
98
99 /* Print the line of text */
100 puts (this_line);
101 }
102
103 total_lines++;
104 } /* long if */
105 } /* while fgets */
106
107 if (count_lines)
108 {
109 /* Just show num. lines that contain the string */
110 printf ("%ld\n", total_lines);
111 }
112
113
114 /* RETURN: If the string was found at least once, returns 1.
115 * If the string was not found at all, returns 0.
116 */
117 return (total_lines > 0 ? 1 : 0);
118 }
119
120
121 /* Show usage */
122 void
123 usage (void)
124 {
125 fprintf (stderr, "FIND: Prints all lines of a file that contain a string\n");
126 fprintf (stderr, "FIND [ /C ] [ /I ] [ /N ] [ /V ] \"string\" [ file... ]\n");
127 fprintf (stderr, " /C Count the number of lines that contain string\n");
128 fprintf (stderr, " /I Ignore case\n");
129 fprintf (stderr, " /N Number the displayed lines, starting at 1\n");
130 fprintf (stderr, " /V Print lines that do not contain the string\n");
131 }
132
133
134 /* Main program */
135 int
136 main (int argc, char **argv)
137 {
138 char *opt, *needle = NULL;
139 int ret = 0;
140
141 int invert_search = 0; /* flag to invert the search */
142 int count_lines = 0; /* flag to whether/not count lines */
143 int number_output = 0; /* flag to print line numbers */
144 int ignore_case = 0; /* flag to be case insensitive */
145
146 FILE *pfile; /* file pointer */
147 int hfind; /* search handle */
148 struct _finddata_t finddata; /* _findfirst, filenext block */
149
150 /* Scan the command line */
151 while ((--argc) && (needle == NULL))
152 {
153 if (*(opt = *++argv) == '/')
154 {
155 switch (opt[1])
156 {
157 case 'c':
158 case 'C': /* Count */
159 count_lines = 1;
160 break;
161
162 case 'i':
163 case 'I': /* Ignore */
164 ignore_case = 1;
165 break;
166
167 case 'n':
168 case 'N': /* Number */
169 number_output = 1;
170 break;
171
172 case 'v':
173 case 'V': /* Not with */
174 invert_search = 1;
175 break;
176
177 default:
178 usage ();
179 exit (2); /* syntax error .. return error 2 */
180 break;
181 }
182 }
183 else
184 {
185 /* Get the string */
186 if (needle == NULL)
187 {
188 /* Assign the string to find */
189 needle = *argv;
190 }
191 }
192 }
193
194 /* Check for search string */
195 if (needle == NULL)
196 {
197 /* No string? */
198 usage ();
199 exit (1);
200 }
201
202 /* Scan the files for the string */
203 if (argc == 0)
204 {
205 ret = find_str (needle, stdin, invert_search, count_lines,
206 number_output, ignore_case);
207 }
208
209 while (--argc >= 0)
210 {
211 hfind = _findfirst (*++argv, &finddata);
212 if (hfind < 0)
213 {
214 /* We were not able to find a file. Display a message and
215 set the exit status. */
216 fprintf (stderr, "FIND: %s: No such file\n", *argv);
217 }
218 else
219 {
220 /* repeat find next file to match the filemask */
221 do
222 {
223 /* We have found a file, so try to open it */
224 if ((pfile = fopen (finddata.name, "r")) != NULL)
225 {
226 printf ("---------------- %s\n", finddata.name);
227 ret = find_str (needle, pfile, invert_search, count_lines,
228 number_output, ignore_case);
229 fclose (pfile);
230 }
231 else
232 {
233 fprintf (stderr, "FIND: %s: Cannot open file\n",
234 finddata.name);
235 }
236 }
237 while (_findnext(hfind, &finddata) > 0);
238 }
239 _findclose(hfind);
240 } /* for each argv */
241
242 /* RETURN: If the string was found at least once, returns 0.
243 * If the string was not found at all, returns 1.
244 * (Note that find_str.c returns the exact opposite values.)
245 */
246 exit ( (ret ? 0 : 1) );
247 }
248