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