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