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