xref: /original-bsd/usr.bin/look/look.c (revision ba762ddc)
1 /*-
2  * Copyright (c) 1987 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1987 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)look.c	4.9 (Berkeley) 04/18/91";
16 #endif /* not lint */
17 
18 #include <sys/types.h>
19 #include <sys/file.h>
20 #include <sys/stat.h>
21 #include <stdio.h>
22 #include <ctype.h>
23 #include "pathnames.h"
24 
25 #define	EOS		'\0'
26 #define	MAXLINELEN	250
27 #define	YES		1
28 
29 static int	fold, dict, len;
30 
31 main(argc, argv)
32 	int	argc;
33 	char	**argv;
34 {
35 	extern char	*optarg;
36 	extern int	optind;
37 	static char	*filename = _PATH_WORDS;
38 	register off_t	bot, mid, top;
39 	register int	c;
40 	struct stat	sb;
41 	char	entry[MAXLINELEN], copy[MAXLINELEN];
42 
43 	while ((c = getopt(argc, argv, "df")) != EOF)
44 		switch((char)c) {
45 		case 'd':
46 			dict = YES;
47 			break;
48 		case 'f':
49 			fold = YES;
50 			break;
51 		case '?':
52 		default:
53 			usage();
54 		}
55 	argv += optind;
56 	argc -= optind;
57 
58 	switch(argc) {
59 	case 1:	/* if default file, set to dictionary order and folding */
60 		dict = fold = YES;
61 		break;
62 	case 2:
63 		filename = argv[1];
64 		break;
65 	default:
66 		usage();
67 	}
68 
69 	if (!freopen(filename, "r", stdin)) {
70 		fprintf(stderr,"look: can't read %s.\n", filename);
71 		exit(2);
72 	}
73 	if (fstat(fileno(stdin), &sb)) {
74 		perror("look: fstat");
75 		exit(2);
76 	}
77 
78 	len = strlen(*argv);
79 	canon(*argv, *argv);
80 	len = strlen(*argv);		/* may have changed */
81 	if (len > MAXLINELEN - 1) {
82 		(void)fprintf(stderr,
83 		    "look: search string is too long.\n");
84 		exit(2);
85 	}
86 
87 	for (bot = 0, top = sb.st_size;;) {
88 		mid = (top + bot) / 2;
89 		(void)fseek(stdin, mid, L_SET);
90 
91 		for (++mid; (c = getchar()) != EOF && c != '\n'; ++mid);
92 		if (!getline(entry))
93 			break;
94 		canon(entry, copy);
95 		if (strncmp(*argv, copy, len) <= 0) {
96 			if (top <= mid)
97 				break;
98 			top = mid;
99 		}
100 		else
101 			bot = mid;
102 	}
103 	(void)fseek(stdin, bot, L_SET);
104 	while (ftell(stdin) < top) {
105 		register int val;
106 
107 		if (!getline(entry))
108 			exit(0);
109 		canon(entry, copy);
110 		if (!(val = strncmp(*argv, copy, len))) {
111 			puts(entry);
112 			break;
113 		}
114 		if (val < 0)
115 			exit(0);
116 	}
117 	while (getline(entry)) {
118 		canon(entry, copy);
119 		if (strncmp(*argv, copy, len))
120 			break;
121 		puts(entry);
122 	}
123 	exit(0);
124 }
125 
126 /*
127  * getline --
128  *	get a line
129  */
130 getline(buf)
131 	register char	*buf;
132 {
133 	register int	c;
134 
135 	for (;;) {
136 		if ((c = getchar()) == EOF)
137 			return(0);
138 		if (c == '\n')
139 			break;
140 		*buf++ = c;
141 	}
142 	*buf = EOS;
143 	return(1);
144 }
145 
146 /*
147  * canon --
148  *	create canonical version of word
149  */
150 canon(src, copy)
151 	register char	*src, *copy;
152 {
153 	register int	cnt;
154 	register char	c;
155 
156 	for (cnt = len + 1; (c = *src++) && cnt; --cnt)
157 		if (!dict || isalnum(c))
158 			*copy++ = fold && isupper(c) ? tolower(c) : c;
159 	*copy = EOS;
160 }
161 
162 /*
163  * usage --
164  *	print a usage message and die
165  */
166 usage()
167 {
168 	(void)fprintf(stderr, "usage: look [-df] string [file]\n");
169 	exit(1);
170 }
171