[TCPIP]
[reactos.git] / base / applications / cmdutils / find / 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 along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 #include <windows.h>
33
34 #include <io.h>
35 #include <dos.h>
36
37 #include "resource.h"
38
39
40 /* Symbol definition */
41 #define MAX_STR 1024
42
43
44 /* This function prints out all lines containing a substring. There are some
45 * conditions that may be passed to the function.
46 *
47 * RETURN: If the string was found at least once, returns 1.
48 * If the string was not found at all, returns 0.
49 */
50 int
51 find_str (char *sz, FILE *p, int invert_search,
52 int count_lines, int number_output, int ignore_case)
53 {
54 int i, length;
55 long line_number = 0, total_lines = 0;
56 char *c, temp_str[MAX_STR], this_line[MAX_STR];
57
58 /* Convert to upper if needed */
59 if (ignore_case)
60 {
61 length = strlen (sz);
62 for (i = 0; i < length; i++)
63 sz[i] = toupper (sz[i]);
64 }
65
66 /* Scan the file until EOF */
67 while (fgets (temp_str, MAX_STR, p) != NULL)
68 {
69 /* Remove the trailing newline */
70 length = strlen (temp_str);
71 if (temp_str[length-1] == '\n')
72 {
73 temp_str[length-1] = '\0';
74 }
75
76 /* Increment number of lines */
77 line_number++;
78 strcpy (this_line, temp_str);
79
80 /* Convert to upper if needed */
81 if (ignore_case)
82 {
83 for (i = 0; i < length; i++)
84 {
85 temp_str[i] = toupper (temp_str[i]);
86 }
87 }
88
89 /* Locate the substring */
90
91 /* strstr() returns a pointer to the first occurrence in the
92 string of the substring */
93 c = strstr (temp_str, sz);
94
95 if ( ((invert_search) ? (c == NULL) : (c != NULL)) )
96 {
97 if (!count_lines)
98 {
99 if (number_output)
100 printf ("%ld:", line_number);
101
102 /* Print the line of text */
103 puts (this_line);
104 }
105
106 total_lines++;
107 } /* long if */
108 } /* while fgets */
109
110 if (count_lines)
111 {
112 /* Just show num. lines that contain the string */
113 printf ("%ld\n", total_lines);
114 }
115
116
117 /* RETURN: If the string was found at least once, returns 1.
118 * If the string was not found at all, returns 0.
119 */
120 return (total_lines > 0 ? 1 : 0);
121 }
122
123 /* Show usage */
124 void
125 usage (void)
126 {
127 TCHAR lpUsage[4096];
128
129 LoadString( GetModuleHandle(NULL), IDS_USAGE, (LPTSTR)lpUsage, 4096);
130 CharToOem(lpUsage, lpUsage);
131 printf( lpUsage );
132 }
133
134
135 /* Main program */
136 int
137 main (int argc, char **argv)
138 {
139 char *opt, *needle = NULL;
140 int ret = 0;
141 TCHAR lpMessage[4096];
142
143 int invert_search = 0; /* flag to invert the search */
144 int count_lines = 0; /* flag to whether/not count lines */
145 int number_output = 0; /* flag to print line numbers */
146 int ignore_case = 0; /* flag to be case insensitive */
147
148 FILE *pfile; /* file pointer */
149 int hfind; /* search handle */
150 struct _finddata_t finddata; /* _findfirst, filenext block */
151
152 /* Scan the command line */
153 while ((--argc) && (needle == NULL))
154 {
155 if (*(opt = *++argv) == '/')
156 {
157 switch (opt[1])
158 {
159 case 'c':
160 case 'C': /* Count */
161 count_lines = 1;
162 break;
163
164 case 'i':
165 case 'I': /* Ignore */
166 ignore_case = 1;
167 break;
168
169 case 'n':
170 case 'N': /* Number */
171 number_output = 1;
172 break;
173
174 case 'v':
175 case 'V': /* Not with */
176 invert_search = 1;
177 break;
178
179 default:
180 usage ();
181 exit (2); /* syntax error .. return error 2 */
182 break;
183 }
184 }
185 else
186 {
187 /* Get the string */
188 if (needle == NULL)
189 {
190 /* Assign the string to find */
191 needle = *argv;
192 }
193 }
194 }
195
196 /* Check for search string */
197 if (needle == NULL)
198 {
199 /* No string? */
200 usage ();
201 exit (1);
202 }
203
204 /* Scan the files for the string */
205 if (argc == 0)
206 {
207 ret = find_str (needle, stdin, invert_search, count_lines,
208 number_output, ignore_case);
209 }
210
211 while (--argc >= 0)
212 {
213 hfind = _findfirst (*++argv, &finddata);
214 if (hfind < 0)
215 {
216 /* We were not able to find a file. Display a message and
217 set the exit status. */
218 LoadString( GetModuleHandle(NULL), IDS_NO_SUCH_FILE, (LPTSTR)lpMessage, 4096);
219 CharToOem(lpMessage, lpMessage);
220 fprintf (stderr, lpMessage, *argv);//
221 }
222 else
223 {
224 /* repeat find next file to match the filemask */
225 do
226 {
227 /* We have found a file, so try to open it */
228 if ((pfile = fopen (finddata.name, "r")) != NULL)
229 {
230 printf ("---------------- %s\n", finddata.name);
231 ret = find_str (needle, pfile, invert_search, count_lines,
232 number_output, ignore_case);
233 fclose (pfile);
234 }
235 else
236 {
237 LoadString(GetModuleHandle(NULL), IDS_CANNOT_OPEN, (LPTSTR)lpMessage, 4096);
238 CharToOem(lpMessage, lpMessage);
239 fprintf (stderr, lpMessage,
240 finddata.name);
241 }
242 }
243 while (_findnext(hfind, &finddata) > 0);
244 }
245 _findclose(hfind);
246 } /* for each argv */
247
248 /* RETURN: If the string was found at least once, returns 0.
249 * If the string was not found at all, returns 1.
250 * (Note that find_str.c returns the exact opposite values.)
251 */
252 exit ( (ret ? 0 : 1) );
253 }
254
255