1 /* findstr.c */ 2 3 /* Copyright (C) 1994-2002, Jim Hall <jhall@freedos.org> */ 4 5 /* Adapted for ReactOS -Edited for Findstr.exe K'Williams */ 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 <windef.h> 33 #include <winbase.h> 34 #include <winuser.h> 35 //#include <io.h> 36 #include <dos.h> 37 38 #include "resource.h" 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, int at_start, int literal_search, 53 int at_end, int reg_express, int exact_match, int sub_dirs, int only_fname) 54 { 55 int i, length; 56 long line_number = 0, total_lines = 0; 57 char *c, temp_str[MAX_STR], this_line[MAX_STR]; 58 59 /* Convert to upper if needed */ 60 if (ignore_case) 61 { 62 length = strlen (sz); 63 for (i = 0; i < length; i++) 64 sz[i] = toupper (sz[i]); 65 } 66 67 /* Scan the file until EOF */ 68 while (fgets (temp_str, MAX_STR, p) != NULL) 69 { 70 /* Remove the trailing newline */ 71 length = strlen (temp_str); 72 if (temp_str[length-1] == '\n') 73 { 74 temp_str[length-1] = '\0'; 75 } 76 77 /* Increment number of lines */ 78 line_number++; 79 strcpy (this_line, temp_str); 80 81 /* Convert to upper if needed */ 82 if (ignore_case) 83 { 84 for (i = 0; i < length; i++) 85 { 86 temp_str[i] = toupper (temp_str[i]); 87 } 88 } 89 90 /* Locate the substring */ 91 92 /* strstr() returns a pointer to the first occurrence in the 93 string of the substring */ 94 c = strstr (temp_str, sz); 95 96 if ( ((invert_search) ? (c == NULL) : (c != NULL)) ) 97 { 98 if (!count_lines) 99 { 100 if (number_output) 101 printf ("%ld:", line_number); 102 103 /* Print the line of text */ 104 puts (this_line); 105 } 106 107 total_lines++; 108 } /* long if */ 109 } /* while fgets */ 110 111 if (count_lines) 112 { 113 /* Just show num. lines that contain the string */ 114 printf ("%ld\n", total_lines); 115 } 116 117 118 /* RETURN: If the string was found at least once, returns 1. 119 * If the string was not found at all, returns 0. 120 */ 121 return (total_lines > 0 ? 1 : 0); 122 } 123 124 /* Show usage */ 125 void 126 usage (void) 127 { 128 TCHAR lpUsage[4096]; 129 130 LoadString( GetModuleHandle(NULL), IDS_USAGE, (LPTSTR)lpUsage, 4096); 131 CharToOem(lpUsage, lpUsage); 132 printf( lpUsage ); 133 } 134 135 136 /* Main program */ 137 int 138 main (int argc, char **argv) 139 { 140 char *opt, *needle = NULL; 141 int ret = 0; 142 TCHAR lpMessage[4096]; 143 144 int invert_search = 0; /* flag to invert the search */ 145 int count_lines = 0; /* flag to whether/not count lines */ 146 int number_output = 0; /* flag to print line numbers */ 147 int ignore_case = 0; /* flag to be case insensitive */ 148 int at_start = 0; /* flag to Match if at the beginning of a line. */ 149 int at_end = 0; /* flag to Match if at the beginning of a line. */ 150 int reg_express = 0; /* flag to use/not use regular expressions */ 151 int exact_match = 0; /* flag to be exact match */ 152 int sub_dirs= 0; /* this and all subdirectories */ 153 int only_fname= 0; /* print only the name of the file*/ 154 int literal_search=0; 155 156 FILE *pfile; /* file pointer */ 157 int hfind; /* search handle */ 158 struct _finddata_t finddata; /* _findfirst, filenext block */ 159 160 /* Scan the command line */ 161 while ((--argc) && (needle == NULL)) 162 { 163 if (*(opt = *++argv) == '/') 164 { 165 switch (opt[1]) 166 { 167 case 'b': 168 case 'B': /* Matches pattern if at the beginning of a line */ 169 at_start = 1; 170 break; 171 172 //case 'c': 173 //case 'C': /* Literal? */ 174 // literal_search = 1; 175 // break; 176 177 case 'e': 178 case 'E': /* matches pattern if at end of line */ 179 at_end = 1; 180 break; 181 182 case 'i': 183 case 'I': /* Ignore */ 184 ignore_case = 1; 185 break; 186 187 case 'm': 188 case 'M': /* only filename */ 189 only_fname = 1; 190 break; 191 192 case 'n': 193 case 'N': /* Number */ 194 number_output = 1; 195 break; 196 197 case 'r': 198 case 'R': /* search strings as regular expressions */ 199 reg_express = 1; 200 break; 201 202 case 's': 203 case 'S': /* search files in child directory too*/ 204 sub_dirs = 1; 205 break; 206 207 case 'v': 208 case 'V': /* Not with */ 209 invert_search = 1; 210 break; 211 212 case 'x': 213 case 'X': /* exact match */ 214 exact_match = 1; 215 break; 216 217 default: 218 usage (); 219 exit (2); /* syntax error .. return error 2 */ 220 break; 221 } 222 } 223 else 224 { 225 /* Get the string */ 226 if (needle == NULL) 227 { 228 /* Assign the string to find */ 229 needle = *argv; 230 } 231 } 232 } 233 234 /* Check for search string */ 235 if (needle == NULL) 236 { 237 /* No string? */ 238 usage (); 239 exit (1); 240 } 241 242 /* Scan the files for the string */ 243 if (argc == 0) 244 { 245 ret = find_str (needle, stdin, invert_search, count_lines, 246 number_output, ignore_case, at_start, literal_search, at_end, reg_express, exact_match, 247 sub_dirs, only_fname); 248 } 249 250 while (--argc >= 0) 251 { 252 hfind = _findfirst (*++argv, &finddata); 253 if (hfind < 0) 254 { 255 /* We were not able to find a file. Display a message and 256 set the exit status. */ 257 LoadString( GetModuleHandle(NULL), IDS_NO_SUCH_FILE, (LPTSTR)lpMessage, 4096); 258 CharToOem(lpMessage, lpMessage); 259 fprintf (stderr, lpMessage, *argv);// 260 } 261 else 262 { 263 /* repeat find next file to match the filemask */ 264 do 265 { 266 /* We have found a file, so try to open it */ 267 if ((pfile = fopen (finddata.name, "r")) != NULL) 268 { 269 printf ("---------------- %s\n", finddata.name); 270 ret = find_str (needle, pfile, invert_search, count_lines, 271 number_output, ignore_case, at_start, literal_search, at_end, reg_express, exact_match, 272 sub_dirs, only_fname); 273 fclose (pfile); 274 } 275 else 276 { 277 LoadString(GetModuleHandle(NULL), IDS_CANNOT_OPEN, (LPTSTR)lpMessage, 4096); 278 CharToOem(lpMessage, lpMessage); 279 fprintf (stderr, lpMessage, 280 finddata.name); 281 } 282 } 283 while (_findnext(hfind, &finddata) > 0); 284 } 285 _findclose(hfind); 286 } /* for each argv */ 287 288 /* RETURN: If the string was found at least once, returns 0. 289 * If the string was not found at all, returns 1. 290 * (Note that find_str.c returns the exact opposite values.) 291 */ 292 exit ( (ret ? 0 : 1) ); 293 } 294 295 296