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