1 /* 2 * Copyright (c) 1980, 1987, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1980, 1987, 1993\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)strings.c 8.2 (Berkeley) 01/28/94"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 20 #include <a.out.h> 21 #include <ctype.h> 22 #include <errno.h> 23 #include <fcntl.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <unistd.h> 28 29 #define DEF_LEN 4 /* default minimum string length */ 30 #define ISSTR(ch) (isascii(ch) && (isprint(ch) || ch == '\t')) 31 32 typedef struct exec EXEC; /* struct exec cast */ 33 34 static long foff; /* offset in the file */ 35 static int hcnt, /* head count */ 36 head_len, /* length of header */ 37 read_len; /* length to read */ 38 static u_char hbfr[sizeof(EXEC)]; /* buffer for struct exec */ 39 40 static void usage(); 41 42 main(argc, argv) 43 int argc; 44 char **argv; 45 { 46 extern char *optarg; 47 extern int optind; 48 register int ch, cnt; 49 register u_char *C; 50 EXEC *head; 51 int exitcode, minlen; 52 short asdata, oflg, fflg; 53 u_char *bfr; 54 char *file, *p; 55 56 /* 57 * for backward compatibility, allow '-' to specify 'a' flag; no 58 * longer documented in the man page or usage string. 59 */ 60 asdata = exitcode = fflg = oflg = 0; 61 minlen = -1; 62 while ((ch = getopt(argc, argv, "-0123456789an:of")) != EOF) 63 switch (ch) { 64 case '0': case '1': case '2': case '3': case '4': 65 case '5': case '6': case '7': case '8': case '9': 66 /* 67 * kludge: strings was originally designed to take 68 * a number after a dash. 69 */ 70 if (minlen == -1) { 71 p = argv[optind - 1]; 72 if (p[0] == '-' && p[1] == ch && !p[2]) 73 minlen = atoi(++p); 74 else 75 minlen = atoi(argv[optind] + 1); 76 } 77 break; 78 case '-': 79 case 'a': 80 asdata = 1; 81 break; 82 case 'f': 83 fflg = 1; 84 break; 85 case 'n': 86 minlen = atoi(optarg); 87 break; 88 case 'o': 89 oflg = 1; 90 break; 91 case '?': 92 default: 93 usage(); 94 } 95 argc -= optind; 96 argv += optind; 97 98 if (minlen == -1) 99 minlen = DEF_LEN; 100 else { 101 (void)fprintf(stderr, "strings: length less than 1\n"); 102 exit (1); 103 } 104 105 if (!(bfr = malloc((u_int)minlen))) { 106 (void)fprintf(stderr, "strings: %s\n", strerror(errno)); 107 exit(1); 108 } 109 bfr[minlen] = '\0'; 110 file = "stdin"; 111 do { 112 if (*argv) { 113 file = *argv++; 114 if (!freopen(file, "r", stdin)) { 115 (void)fprintf(stderr, 116 "strings: %s: %s\n", file, strerror(errno)); 117 exitcode = 1; 118 goto nextfile; 119 } 120 } 121 foff = 0; 122 #define DO_EVERYTHING() {read_len = -1; head_len = 0; goto start;} 123 read_len = -1; 124 if (asdata) 125 DO_EVERYTHING() 126 else { 127 head = (EXEC *)hbfr; 128 if ((head_len = 129 read(fileno(stdin), head, sizeof(EXEC))) == -1) 130 DO_EVERYTHING() 131 if (head_len == sizeof(EXEC) && !N_BADMAG(*head)) { 132 foff = N_TXTOFF(*head); 133 if (fseek(stdin, foff, SEEK_SET) == -1) 134 DO_EVERYTHING() 135 read_len = head->a_text + head->a_data; 136 head_len = 0; 137 } 138 else 139 hcnt = 0; 140 } 141 start: 142 for (cnt = 0; (ch = getch()) != EOF;) { 143 if (ISSTR(ch)) { 144 if (!cnt) 145 C = bfr; 146 *C++ = ch; 147 if (++cnt < minlen) 148 continue; 149 if (fflg) 150 printf("%s:", file); 151 if (oflg) 152 printf("%07ld %s", 153 foff - minlen, (char *)bfr); 154 else 155 printf("%s", bfr); 156 while ((ch = getch()) != EOF && ISSTR(ch)) 157 putchar((char)ch); 158 putchar('\n'); 159 } 160 cnt = 0; 161 } 162 nextfile: ; 163 } while (*argv); 164 exit(exitcode); 165 } 166 167 /* 168 * getch -- 169 * get next character from wherever 170 */ 171 getch() 172 { 173 ++foff; 174 if (head_len) { 175 if (hcnt < head_len) 176 return((int)hbfr[hcnt++]); 177 head_len = 0; 178 } 179 if (read_len == -1 || read_len-- > 0) 180 return(getchar()); 181 return(EOF); 182 } 183 184 static void 185 usage() 186 { 187 (void)fprintf(stderr, 188 "usage: strings [-afo] [-n length] [file ... ]\n"); 189 exit(1); 190 } 191