Print this page
3737 grep does not support -H option
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/grep/grep.c
+++ new/usr/src/cmd/grep/grep.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 28 /* All Rights Reserved */
29 29
30 30 /* Copyright (c) 1987, 1988 Microsoft Corporation */
31 31 /* All Rights Reserved */
32 32
33 33 /* Copyright 2012 Nexenta Systems, Inc. All rights reserved. */
34 34
35 35 /*
36 36 * grep -- print lines matching (or not matching) a pattern
37 37 *
38 38 * status returns:
39 39 * 0 - ok, and some matches
40 40 * 1 - ok, but no matches
41 41 * 2 - some error
42 42 */
43 43
44 44 #include <sys/types.h>
45 45
46 46 #include <ctype.h>
47 47 #include <fcntl.h>
48 48 #include <locale.h>
49 49 #include <memory.h>
50 50 #include <regexpr.h>
51 51 #include <stdio.h>
52 52 #include <stdlib.h>
53 53 #include <string.h>
54 54 #include <unistd.h>
55 55 #include <ftw.h>
56 56 #include <limits.h>
57 57 #include <sys/param.h>
58 58
59 59 static const char *errstr[] = {
60 60 "Range endpoint too large.",
61 61 "Bad number.",
62 62 "``\\digit'' out of range.",
63 63 "No remembered search string.",
64 64 "\\( \\) imbalance.",
65 65 "Too many \\(.",
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
66 66 "More than 2 numbers given in \\{ \\}.",
67 67 "} expected after \\.",
68 68 "First number exceeds second in \\{ \\}.",
69 69 "[ ] imbalance.",
70 70 "Regular expression overflow.",
71 71 "Illegal byte sequence.",
72 72 "Unknown regexp error code!!",
73 73 NULL
74 74 };
75 75
76 +#define STDIN_FILENAME gettext("(standard input)")
77 +
76 78 #define errmsg(msg, arg) (void) fprintf(stderr, gettext(msg), arg)
77 79 #define BLKSIZE 512
78 80 #define GBUFSIZ 8192
79 81 #define MAX_DEPTH 1000
80 82
81 83 static int temp;
82 84 static long long lnum;
83 85 static char *linebuf;
84 86 static char *prntbuf = NULL;
85 87 static long fw_lPrntBufLen = 0;
86 88 static int nflag;
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
87 89 static int bflag;
88 90 static int lflag;
89 91 static int cflag;
90 92 static int rflag;
91 93 static int Rflag;
92 94 static int vflag;
93 95 static int sflag;
94 96 static int iflag;
95 97 static int wflag;
96 98 static int hflag;
99 +static int Hflag;
97 100 static int qflag;
98 101 static int errflg;
99 102 static int nfile;
100 103 static long long tln;
101 104 static int nsucc;
102 105 static int outfn = 0;
103 106 static int nlflag;
104 107 static char *ptr, *ptrend;
105 108 static char *expbuf;
106 109
107 110 static void execute(const char *, int);
108 111 static void regerr(int);
109 112 static void prepare(const char *);
110 113 static int recursive(const char *, const struct stat *, int, struct FTW *);
111 114 static int succeed(const char *);
112 115
113 116 int
114 117 main(int argc, char **argv)
115 118 {
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
116 119 int c;
117 120 char *arg;
118 121 extern int optind;
119 122
120 123 (void) setlocale(LC_ALL, "");
121 124 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
122 125 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
123 126 #endif
124 127 (void) textdomain(TEXT_DOMAIN);
125 128
126 - while ((c = getopt(argc, argv, "hqblcnRrsviyw")) != -1)
129 + while ((c = getopt(argc, argv, "hHqblcnRrsviyw")) != -1)
127 130 switch (c) {
131 + /* based on options order h or H is set as in GNU grep */
128 132 case 'h':
129 133 hflag++;
134 + Hflag = 0; /* h excludes H */
135 + break;
136 + case 'H':
137 + if (!lflag) /* H is excluded by l */
138 + Hflag++;
139 + hflag = 0; /* H excludes h */
130 140 break;
131 141 case 'q': /* POSIX: quiet: status only */
132 142 qflag++;
133 143 break;
134 144 case 'v':
135 145 vflag++;
136 146 break;
137 147 case 'c':
138 148 cflag++;
139 149 break;
140 150 case 'n':
141 151 nflag++;
142 152 break;
143 153 case 'R':
144 154 Rflag++;
145 155 /* FALLTHROUGH */
146 156 case 'r':
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
147 157 rflag++;
148 158 break;
149 159 case 'b':
150 160 bflag++;
151 161 break;
152 162 case 's':
153 163 sflag++;
154 164 break;
155 165 case 'l':
156 166 lflag++;
167 + Hflag = 0; /* l excludes H */
157 168 break;
158 169 case 'y':
159 170 case 'i':
160 171 iflag++;
161 172 break;
162 173 case 'w':
163 174 wflag++;
164 175 break;
165 176 case '?':
166 177 errflg++;
167 178 }
168 179
169 180 if (errflg || (optind >= argc)) {
170 - errmsg("Usage: grep [-c|-l|-q] [-r|-R] -hbnsviw "
181 + errmsg("Usage: grep [-c|-l|-q] [-r|-R] -hHbnsviw "
171 182 "pattern file . . .\n",
172 183 (char *)NULL);
173 184 exit(2);
174 185 }
175 186
176 187 argv = &argv[optind];
177 188 argc -= optind;
178 189 nfile = argc - 1;
179 190
180 191 if (strrchr(*argv, '\n') != NULL)
181 192 regerr(41);
182 193
183 194 if (iflag) {
184 195 for (arg = *argv; *arg != NULL; ++arg)
185 196 *arg = (char)tolower((int)((unsigned char)*arg));
186 197 }
187 198
188 199 if (wflag) {
189 200 unsigned int wordlen;
190 201 char *wordbuf;
191 202
192 203 wordlen = strlen(*argv) + 5; /* '\\' '<' *argv '\\' '>' '\0' */
193 204 if ((wordbuf = malloc(wordlen)) == NULL) {
194 205 errmsg("grep: Out of memory for word\n", (char *)NULL);
195 206 exit(2);
196 207 }
197 208
198 209 (void) strcpy(wordbuf, "\\<");
199 210 (void) strcat(wordbuf, *argv);
200 211 (void) strcat(wordbuf, "\\>");
201 212 *argv = wordbuf;
202 213 }
203 214
204 215 expbuf = compile(*argv, (char *)0, (char *)0);
205 216 if (regerrno)
206 217 regerr(regerrno);
207 218
208 219 if (--argc == 0)
209 220 execute(NULL, 0);
210 221 else
211 222 while (argc-- > 0)
212 223 prepare(*++argv);
213 224
214 225 return (nsucc == 2 ? 2 : (nsucc == 0 ? 1 : 0));
215 226 }
216 227
217 228 static void
218 229 prepare(const char *path)
219 230 {
220 231 struct stat st;
221 232 int walkflags = FTW_CHDIR;
222 233 char *buf = NULL;
223 234
224 235 if (rflag) {
225 236 if (stat(path, &st) != -1 &&
226 237 (st.st_mode & S_IFMT) == S_IFDIR) {
227 238 outfn = 1;
228 239
229 240 /*
230 241 * Add trailing slash if arg
231 242 * is directory, to resolve symlinks.
232 243 */
233 244 if (path[strlen(path) - 1] != '/') {
234 245 (void) asprintf(&buf, "%s/", path);
235 246 if (buf != NULL)
236 247 path = buf;
237 248 }
238 249
239 250 /*
240 251 * Search through subdirs if path is directory.
241 252 * Don't follow symlinks if Rflag is not set.
242 253 */
243 254 if (!Rflag)
244 255 walkflags |= FTW_PHYS;
245 256
246 257 if (nftw(path, recursive, MAX_DEPTH, walkflags) != 0) {
247 258 if (!sflag)
248 259 errmsg("grep: can't open %s\n", path);
249 260 nsucc = 2;
250 261 }
251 262 return;
252 263 }
253 264 }
254 265 execute(path, 0);
255 266 }
256 267
257 268 static int
258 269 recursive(const char *name, const struct stat *statp, int info, struct FTW *ftw)
259 270 {
260 271 /*
261 272 * process files and follow symlinks if Rflag set.
262 273 */
263 274 if (info != FTW_F) {
264 275 if (!sflag &&
265 276 (info == FTW_SLN || info == FTW_DNR || info == FTW_NS)) {
266 277 /* report broken symlinks and unreadable files */
267 278 errmsg("grep: can't open %s\n", name);
268 279 }
269 280 return (0);
270 281 }
271 282
272 283 /* skip devices and pipes if Rflag is not set */
273 284 if (!Rflag && !S_ISREG(statp->st_mode))
274 285 return (0);
275 286
276 287 /* pass offset to relative name from FTW_CHDIR */
277 288 execute(name, ftw->base);
278 289 return (0);
279 290 }
280 291
281 292 static void
282 293 execute(const char *file, int base)
283 294 {
284 295 char *lbuf, *p;
285 296 long count;
286 297 long offset = 0;
287 298 char *next_ptr = NULL;
288 299 long next_count = 0;
289 300
290 301 tln = 0;
291 302
↓ open down ↓ |
111 lines elided |
↑ open up ↑ |
292 303 if (prntbuf == NULL) {
293 304 fw_lPrntBufLen = GBUFSIZ + 1;
294 305 if ((prntbuf = malloc(fw_lPrntBufLen)) == NULL) {
295 306 exit(2); /* out of memory - BAIL */
296 307 }
297 308 if ((linebuf = malloc(fw_lPrntBufLen)) == NULL) {
298 309 exit(2); /* out of memory - BAIL */
299 310 }
300 311 }
301 312
302 - if (file == NULL)
313 + if (file == NULL) {
303 314 temp = 0;
304 - else if ((temp = open(file + base, O_RDONLY)) == -1) {
315 + file = STDIN_FILENAME;
316 + } else if ((temp = open(file + base, O_RDONLY)) == -1) {
305 317 if (!sflag)
306 318 errmsg("grep: can't open %s\n", file);
307 319 nsucc = 2;
308 320 return;
309 321 }
310 322
311 323 /* read in first block of bytes */
312 324 if ((count = read(temp, prntbuf, GBUFSIZ)) <= 0) {
313 325 (void) close(temp);
314 326
315 327 if (cflag && !qflag) {
316 - if (nfile > 1 && !hflag && file)
328 + if (Hflag || (nfile > 1 && !hflag))
317 329 (void) fprintf(stdout, "%s:", file);
318 330 if (!rflag)
319 331 (void) fprintf(stdout, "%lld\n", tln);
320 332 }
321 333 return;
322 334 }
323 335
324 336 lnum = 0;
325 337 ptr = prntbuf;
326 338 for (;;) {
327 339 /* look for next newline */
328 340 if ((ptrend = memchr(ptr + offset, '\n', count)) == NULL) {
329 341 offset += count;
330 342
331 343 /*
332 344 * shift unused data to the beginning of the buffer
333 345 */
334 346 if (ptr > prntbuf) {
335 347 (void) memmove(prntbuf, ptr, offset);
336 348 ptr = prntbuf;
337 349 }
338 350
339 351 /*
340 352 * re-allocate a larger buffer if this one is full
341 353 */
342 354 if (offset + GBUFSIZ > fw_lPrntBufLen) {
343 355 /*
344 356 * allocate a new buffer and preserve the
345 357 * contents...
346 358 */
347 359 fw_lPrntBufLen += GBUFSIZ;
348 360 if ((prntbuf = realloc(prntbuf,
349 361 fw_lPrntBufLen)) == NULL)
350 362 exit(2);
351 363
352 364 /*
353 365 * set up a bigger linebuffer (this is only used
354 366 * for case insensitive operations). Contents do
355 367 * not have to be preserved.
356 368 */
357 369 free(linebuf);
358 370 if ((linebuf = malloc(fw_lPrntBufLen)) == NULL)
359 371 exit(2);
360 372
361 373 ptr = prntbuf;
362 374 }
363 375
364 376 p = prntbuf + offset;
365 377 if ((count = read(temp, p, GBUFSIZ)) > 0)
366 378 continue;
367 379
368 380 if (offset == 0)
369 381 /* end of file already reached */
370 382 break;
371 383
372 384 /* last line of file has no newline */
373 385 ptrend = ptr + offset;
374 386 nlflag = 0;
375 387 } else {
376 388 next_ptr = ptrend + 1;
377 389 next_count = offset + count - (next_ptr - ptr);
378 390 nlflag = 1;
379 391 }
380 392 lnum++;
381 393 *ptrend = '\0';
382 394
383 395 if (iflag) {
384 396 /*
385 397 * Make a lower case copy of the record
386 398 */
387 399 p = ptr;
388 400 for (lbuf = linebuf; p < ptrend; )
389 401 *lbuf++ = (char)tolower((int)
390 402 (unsigned char)*p++);
391 403 *lbuf = '\0';
392 404 lbuf = linebuf;
393 405 } else
394 406 /*
395 407 * Use record as is
396 408 */
397 409 lbuf = ptr;
398 410
399 411 /* lflag only once */
400 412 if ((step(lbuf, expbuf) ^ vflag) && succeed(file) == 1)
401 413 break;
402 414
↓ open down ↓ |
76 lines elided |
↑ open up ↑ |
403 415 if (!nlflag)
404 416 break;
405 417
406 418 ptr = next_ptr;
407 419 count = next_count;
408 420 offset = 0;
409 421 }
410 422 (void) close(temp);
411 423
412 424 if (cflag && !qflag) {
413 - if (!hflag && file && (nfile > 1 ||
414 - (rflag && outfn)))
425 + if (Hflag || (!hflag && ((nfile > 1) ||
426 + (rflag && outfn))))
415 427 (void) fprintf(stdout, "%s:", file);
416 428 (void) fprintf(stdout, "%lld\n", tln);
417 429 }
418 430 }
419 431
420 432 static int
421 433 succeed(const char *f)
422 434 {
423 435 int nchars;
424 436 nsucc = (nsucc == 2) ? 2 : 1;
425 437
426 - if (f == NULL)
427 - f = "<stdin>";
428 -
429 438 if (qflag) {
430 439 /* no need to continue */
431 440 return (1);
432 441 }
433 442
434 443 if (cflag) {
435 444 tln++;
436 445 return (0);
437 446 }
438 447
439 448 if (lflag) {
440 449 (void) fprintf(stdout, "%s\n", f);
441 450 return (1);
442 451 }
443 452
444 - if (!hflag && (nfile > 1 || (rflag && outfn))) {
453 + if (Hflag || (!hflag && (nfile > 1 || (rflag && outfn)))) {
445 454 /* print filename */
446 455 (void) fprintf(stdout, "%s:", f);
447 456 }
448 457
449 458 if (bflag)
450 459 /* print block number */
451 460 (void) fprintf(stdout, "%lld:", (offset_t)
452 461 ((lseek(temp, (off_t)0, SEEK_CUR) - 1) / BLKSIZE));
453 462
454 463 if (nflag)
455 464 /* print line number */
456 465 (void) fprintf(stdout, "%lld:", lnum);
457 466
458 467 if (nlflag) {
459 468 /* newline at end of line */
460 469 *ptrend = '\n';
461 470 nchars = ptrend - ptr + 1;
462 471 } else {
463 472 /* don't write sentinel \0 */
464 473 nchars = ptrend - ptr;
465 474 }
466 475
467 476 (void) fwrite(ptr, 1, nchars, stdout);
468 477 return (0);
469 478 }
470 479
471 480 static void
472 481 regerr(int err)
473 482 {
474 483 errmsg("grep: RE error %d: ", err);
475 484 switch (err) {
476 485 case 11:
477 486 err = 0;
478 487 break;
479 488 case 16:
480 489 err = 1;
481 490 break;
482 491 case 25:
483 492 err = 2;
484 493 break;
485 494 case 41:
486 495 err = 3;
487 496 break;
488 497 case 42:
489 498 err = 4;
490 499 break;
491 500 case 43:
492 501 err = 5;
493 502 break;
494 503 case 44:
495 504 err = 6;
496 505 break;
497 506 case 45:
498 507 err = 7;
499 508 break;
500 509 case 46:
501 510 err = 8;
502 511 break;
503 512 case 49:
504 513 err = 9;
505 514 break;
506 515 case 50:
507 516 err = 10;
508 517 break;
509 518 case 67:
510 519 err = 11;
511 520 break;
512 521 default:
513 522 err = 12;
514 523 break;
515 524 }
516 525
517 526 errmsg("%s\n", gettext(errstr[err]));
518 527 exit(2);
519 528 }
↓ open down ↓ |
65 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX