xref: /original-bsd/usr.bin/look/look.c (revision 3588a932)
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.8 (Berkeley) 03/01/91";
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 #include "pathnames.h"
23 
24 #define	EOS		'\0'
25 #define	MAXLINELEN	250
26 #define	YES		1
27 
28 static int	fold, dict, len;
29 
30 main(argc, argv)
31 	int	argc;
32 	char	**argv;
33 {
34 	extern char	*optarg;
35 	extern int	optind;
36 	static char	*filename = _PATH_WORDS;
37 	register off_t	bot, mid, top;
38 	register int	c;
39 	struct stat	sb;
40 	char	entry[MAXLINELEN], copy[MAXLINELEN];
41 
42 	while ((c = getopt(argc, argv, "df")) != EOF)
43 		switch((char)c) {
44 		case 'd':
45 			dict = YES;
46 			break;
47 		case 'f':
48 			fold = YES;
49 			break;
50 		case '?':
51 		default:
52 			usage();
53 		}
54 	argv += optind;
55 	argc -= optind;
56 
57 	switch(argc) {
58 	case 1:	/* if default file, set to dictionary order and folding */
59 		dict = fold = YES;
60 		break;
61 	case 2:
62 		filename = argv[1];
63 		break;
64 	default:
65 		usage();
66 	}
67 
68 	if (!freopen(filename, "r", stdin)) {
69 		fprintf(stderr,"look: can't read %s.\n", filename);
70 		exit(2);
71 	}
72 	if (fstat(fileno(stdin), &sb)) {
73 		perror("look: fstat");
74 		exit(2);
75 	}
76 
77 	len = strlen(*argv);
78 	canon(*argv, *argv);
79 	len = strlen(*argv);		/* may have changed */
80 	if (len > MAXLINELEN - 1) {
81 		(void)fprintf(stderr,
82 		    "look: search string is too long.\n");
83 		exit(2);
84 	}
85 
86 	for (bot = 0, top = sb.st_size;;) {
87 		mid = (top + bot) / 2;
88 		(void)fseek(stdin, mid, L_SET);
89 
90 		for (++mid; (c = getchar()) != EOF && c != '\n'; ++mid);
91 		if (!getline(entry))
92 			break;
93 		canon(entry, copy);
94 		if (strncmp(*argv, copy, len) <= 0) {
95 			if (top <= mid)
96 				break;
97 			top = mid;
98 		}
99 		else
100 			bot = mid;
101 	}
102 	(void)fseek(stdin, bot, L_SET);
103 	while (ftell(stdin) < top) {
104 		register int val;
105 
106 		if (!getline(entry))
107 			exit(0);
108 		canon(entry, copy);
109 		if (!(val = strncmp(*argv, copy, len))) {
110 			puts(entry);
111 			break;
112 		}
113 		if (val < 0)
114 			exit(0);
115 	}
116 	while (getline(entry)) {
117 		canon(entry, copy);
118 		if (strncmp(*argv, copy, len))
119 			break;
120 		puts(entry);
121 	}
122 	exit(0);
123 }
124 
125 /*
126  * getline --
127  *	get a line
128  */
129 getline(buf)
130 	register char	*buf;
131 {
132 	register int	c;
133 
134 	for (;;) {
135 		if ((c = getchar()) == EOF)
136 			return(0);
137 		if (c == '\n')
138 			break;
139 		*buf++ = c;
140 	}
141 	*buf = EOS;
142 	return(1);
143 }
144 
145 /*
146  * canon --
147  *	create canonical version of word
148  */
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 usage()
166 {
167 	(void)fprintf(stderr, "usage: look [-df] string [file]\n");
168 	exit(1);
169 }
170