4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 /* Copyright (c) 1987, 1988 Microsoft Corporation */
31 /* All Rights Reserved */
34 * Copyright 2013 Damian Bogel. All rights reserved.
38 * fgrep -- print all lines containing any of a set of keywords
41 * 0 - ok, and some matches
42 * 1 - ok, but no matches
48 #include <sys/types.h>
60 #define WIDTH1 WW._eucw1
61 #define WIDTH2 WW._eucw2
62 #define WIDTH3 WW._eucw3
63 #define MULTI_BYTE WW._multibyte
64 #define GETONE(lc, p) \
65 cw = ISASCII(lc = (unsigned char)*p++) ? 1 : \
66 (ISSET2(lc) ? WIDTH2 : \
67 (ISSET3(lc) ? WIDTH3 : WIDTH1)); \
68 if (--cw > --ccount) { \
71 lc = (lc << 7) | ((*p++) & 0177); \
72 if (p >= &buf[fw_lBufsiz + BUFSIZ]) { \
74 /* Increase the buffer size */ \
75 fw_lBufsiz += BUFSIZ; \
76 if ((buf = realloc(buf, \
77 fw_lBufsiz + BUFSIZ)) == NULL) { \
78 exit(2); /* out of memory */ \
81 p = &buf[fw_lBufsiz]; \
83 /* shift the buffer contents down */ \
84 (void) memmove(buf, nlp, \
85 &buf[fw_lBufsiz + BUFSIZ] - nlp);\
90 if (p > &buf[fw_lBufsiz]) { \
91 if ((ccount = fread(p, sizeof (char), \
92 &buf[fw_lBufsiz + BUFSIZ] - p, fptr))\
94 } else if ((ccount = fread(p, \
95 sizeof (char), BUFSIZ, fptr)) <= 0) \
97 blkno += (long long)ccount; \
101 lc = (lc << 7) | ((*p++) & 0177)
104 * The same() macro and letter() function were inserted to allow for
105 * the -i option work for the multi-byte environment.
109 (a == b || iflag && (!MULTI_BYTE || ISASCII(a)) && (a ^ b) == ' ' && \
110 letter(a) == letter(b))
112 #define STDIN_FILENAME gettext("(standard input)")
121 } *w
= NULL
, *smax
, *q
;
125 int bflag
, cflag
, lflag
, fflag
, nflag
, vflag
, xflag
, eflag
, qflag
;
126 int Hflag
, hflag
, iflag
;
134 off_t input_size
= 0;
136 void execute(char *);
141 static long fw_lBufsiz
= 0;
144 main(int argc
, char **argv
)
148 struct stat file_stat
;
150 (void) setlocale(LC_ALL
, "");
151 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
152 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
154 (void) textdomain(TEXT_DOMAIN
);
156 while ((c
= getopt(argc
, argv
, "Hhybcie:f:lnvxqs")) != EOF
)
160 case 's': /* Solaris: legacy option */
187 input_size
= strlen(argptr
);
192 wordf
= fopen(optarg
, "r");
194 (void) fprintf(stderr
,
195 gettext("fgrep: can't open %s\n"),
200 if (fstat(fileno(wordf
), &file_stat
) == 0) {
201 input_size
= file_stat
.st_size
;
203 (void) fprintf(stderr
,
204 gettext("fgrep: can't fstat %s\n"),
232 if (errflg
|| ((argc
<= 0) && !fflag
&& !eflag
)) {
233 (void) printf(gettext("usage: fgrep [ -bcHhilnqsvx ] "
234 "[ -e exp ] [ -f file ] [ strings ] [ file ] ...\n"));
237 if (!eflag
&& !fflag
) {
238 argptr
= argv
[optind
];
239 input_size
= strlen(argptr
);
246 * Normally we need one struct words for each letter in the pattern
247 * plus one terminating struct words with outp = 1, but when -x option
248 * is specified we require one more struct words for `\n` character so we
249 * calculate the input_size as below. We add extra 1 because
250 * (input_size/2) rounds off odd numbers
254 input_size
= input_size
+ (input_size
/2) + 1;
259 w
= (struct words
*)calloc(input_size
, sizeof (struct words
));
261 (void) fprintf(stderr
,
262 gettext("fgrep: could not allocate "
263 "memory for wordlist\n"));
268 if ((WIDTH1
== 0) && (WIDTH2
== 0) &&
271 * If non EUC-based locale,
272 * assume WIDTH1 is 1.
282 argv
= &argv
[optind
];
284 execute((char *)NULL
);
286 while (--argc
>= 0) {
295 return (retcode
!= 0 ? retcode
: nsucc
== 0);
304 static char *buf
= NULL
;
312 if ((buf
= malloc(fw_lBufsiz
+ BUFSIZ
)) == NULL
) {
313 exit(2); /* out of memory */
318 if ((fptr
= fopen(file
, "r")) == NULL
) {
319 (void) fprintf(stderr
,
320 gettext("fgrep: can't open %s\n"), file
);
326 file
= STDIN_FILENAME
;
340 if (p
>= &buf
[fw_lBufsiz
+ BUFSIZ
]) {
342 /* increase the buffer size */
343 fw_lBufsiz
+= BUFSIZ
;
344 if ((buf
= realloc(buf
,
345 fw_lBufsiz
+ BUFSIZ
)) == NULL
) {
346 exit(2); /* out of memory */
349 p
= &buf
[fw_lBufsiz
];
351 /* shift the buffer down */
352 (void) memmove(buf
, nlp
,
353 &buf
[fw_lBufsiz
+ BUFSIZ
]
360 if (p
> &buf
[fw_lBufsiz
]) {
361 if ((ccount
= fread(p
, sizeof (char),
362 &buf
[fw_lBufsiz
+ BUFSIZ
] - p
, fptr
))
365 } else if ((ccount
= fread(p
, sizeof (char),
368 blkno
+= (long long)ccount
;
372 if (same(c
->inp
, lc
)) {
374 } else if (c
->link
!= 0) {
383 if (same(c
->inp
, lc
)) {
385 } else if (c
->link
!= 0) {
399 if (p
== &buf
[fw_lBufsiz
+ BUFSIZ
]) {
401 /* increase buffer size */
402 fw_lBufsiz
+= BUFSIZ
;
403 if ((buf
= realloc(buf
, fw_lBufsiz
+ BUFSIZ
)) == NULL
) {
404 exit(2); /* out of memory */
407 p
= &buf
[fw_lBufsiz
];
409 /* shift buffer down */
410 (void) memmove(buf
, nlp
, &buf
[fw_lBufsiz
+ BUFSIZ
] - nlp
);
415 if (p
> &buf
[fw_lBufsiz
]) {
416 if ((ccount
= fread(p
, sizeof (char),
417 &buf
[fw_lBufsiz
+ BUFSIZ
] - p
, fptr
)) <= 0) break;
418 } else if ((ccount
= fread(p
, sizeof (char), BUFSIZ
,
420 blkno
+= (long long)ccount
;
424 if ((vflag
&& (failed
== 0 || xflag
== 0)) ||
425 (vflag
== 0 && xflag
&& failed
))
429 if (lflag
|| qflag
) {
431 (void) printf("%s\n", file
);
438 if (Hflag
|| (nfile
> 1 && !hflag
))
439 (void) printf("%s:", file
);
441 (void) printf("%lld:",
442 (blkno
- (long long)(ccount
-1))
445 (void) printf("%lld:", lnum
);
447 while (nlp
< &buf
[fw_lBufsiz
+ BUFSIZ
])
448 (void) putchar(*nlp
++);
452 (void) putchar(*nlp
++);
472 if (cflag
&& !qflag
) {
473 if (Hflag
|| (nfile
> 1 && !hflag
))
474 (void) printf("%s:", file
);
475 (void) printf("%lld\n", tln
);
483 /* appends a newline to shell quoted argument list so */
484 /* the list looks like it came from an ed style file */
492 if ((b
= getc(wordf
)) == EOF
)
494 cw
= ISASCII(c
= (wchar_t)b
) ? 1 :
495 (ISSET2(c
) ? WIDTH2
: (ISSET3(c
) ? WIDTH3
: WIDTH1
));
497 if ((b
= getc(wordf
)) == EOF
)
499 c
= (c
<< 7) | (b
& 0177);
501 return (iflag
? letter(c
) : c
);
508 cw
= ISASCII(c
= (unsigned char)*argptr
++) ? 1 :
509 (ISSET2(c
) ? WIDTH2
: (ISSET3(c
) ? WIDTH3
: WIDTH1
));
512 c
= (c
<< 7) | ((*argptr
++) & 0177);
518 return (iflag
? letter(c
) : c
);
547 if (smax
>= &w
[input_size
-1])
567 if (smax
>= &w
[input_size
-1])
581 if (smax
>= &w
[input_size
-1])
585 } while ((c
= getargc()) != '\n' && c
!= EOF
);
589 if (smax
>= &w
[input_size
-1])
600 * This function is an unexpected condition, since input_size should have been
601 * calculated correctly before hand.
607 (void) fprintf(stderr
, gettext("fgrep: wordlist too large\n"));
615 struct words
**queue
= NULL
;
618 * front and rear are pointers used to traverse the global words
619 * structure "w" which contains the data of input pattern file
621 struct words
**front
, **rear
;
623 unsigned long frontoffset
= 0, rearoffset
= 0;
627 if ((queue
= (struct words
**)calloc(qsize
, sizeof (struct words
*)))
632 front
= rear
= queue
;
637 * Reallocates the queue if the number of distinct starting
638 * character of patterns exceeds the qsize value
640 if (rear
>= &queue
[qsize
- 1]) {
641 frontoffset
= front
- queue
;
642 rearoffset
= rear
- queue
;
644 if ((queue
= (struct words
**)realloc(queue
,
645 qsize
* sizeof (struct words
*))) == NULL
) {
649 front
= queue
+ frontoffset
;
650 rear
= queue
+ rearoffset
;
653 if ((s
= s
->link
) != 0) {
657 while (rear
!= front
) {
660 if ((c
= s
->inp
) != 0) {
661 *rear
++ = (q
= s
->nst
);
663 * Reallocate the queue if the rear pointer reaches the end
666 if (rear
>= &queue
[qsize
- 1]) {
667 frontoffset
= front
- queue
;
668 rearoffset
= rear
- queue
;
670 if ((queue
= (struct words
**)realloc(queue
,
671 qsize
* sizeof (struct words
*))) == NULL
) {
675 front
= queue
+ frontoffset
;
676 rear
= queue
+ rearoffset
;
682 if (state
->inp
== c
) {
684 q
->fail
= state
->nst
;
685 if ((state
->nst
)->out
== 1)
687 if ((q
= q
->link
) != 0)
689 } else if ((state
= state
->link
) != 0)
692 if ((s
= s
->link
) != 0)
700 if (c
>= 'a' && c
<= 'z')
702 if (c
>= 'A' && c
<= 'Z')
703 return (c
+ 'a' - 'A');