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.3 (Berkeley) 08/05/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 nothing set, default to dictionary order and folding */ 58 if (!dict && !fold) 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 fputs("look: search string is too long.\n", stderr); 82 exit(2); 83 } 84 85 for (bot = 0, top = sb.st_size;;) { 86 mid = (top + bot) / 2; 87 (void)fseek(stdin, mid, L_SET); 88 89 for (++mid; (c = getchar()) != EOF && c != '\n'; ++mid); 90 if (!getline(entry)) 91 break; 92 canon(entry, copy); 93 if (strncmp(*argv, copy, len) <= 0) { 94 if (top <= mid) 95 break; 96 top = mid; 97 } 98 else 99 bot = mid; 100 } 101 (void)fseek(stdin, bot, L_SET); 102 while (ftell(stdin) < top) { 103 register int val; 104 105 if (!getline(entry)) 106 exit(0); 107 canon(entry, copy); 108 if (!(val = strncmp(*argv, copy, len))) { 109 puts(entry); 110 break; 111 } 112 if (val < 0) 113 exit(0); 114 } 115 while (getline(entry)) { 116 canon(entry, copy); 117 if (strncmp(*argv, copy, len)) 118 break; 119 puts(entry); 120 } 121 exit(0); 122 } 123 124 /* 125 * getline -- 126 * get a line 127 */ 128 static 129 getline(buf) 130 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 static 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 static 167 usage() 168 { 169 fputs("usage: look [-df] string [file]\n", stderr); 170 exit(1); 171 } 172