xref: /original-bsd/usr.bin/strings/strings.c (revision 168d7fa9)
15d82ecf4Sdist /*
23616f2cbSbostic  * Copyright (c) 1980, 1987, 1993
33616f2cbSbostic  *	The Regents of the University of California.  All rights reserved.
4654d9ca0Sbostic  *
5179c5b05Sbostic  * %sccs.include.redist.c%
65d82ecf4Sdist  */
75d82ecf4Sdist 
8cb535708Ssam #ifndef lint
93616f2cbSbostic static char copyright[] =
103616f2cbSbostic "@(#) Copyright (c) 1980, 1987, 1993\n\
113616f2cbSbostic 	The Regents of the University of California.  All rights reserved.\n";
12654d9ca0Sbostic #endif /* not lint */
135d82ecf4Sdist 
145d82ecf4Sdist #ifndef lint
15*168d7fa9Sbostic static char sccsid[] = "@(#)strings.c	8.2 (Berkeley) 01/28/94";
16654d9ca0Sbostic #endif /* not lint */
17cb535708Ssam 
18dbf62afdSbostic #include <sys/types.h>
19*168d7fa9Sbostic 
20dbf62afdSbostic #include <a.out.h>
21dbf62afdSbostic #include <ctype.h>
22*168d7fa9Sbostic #include <errno.h>
23*168d7fa9Sbostic #include <fcntl.h>
24*168d7fa9Sbostic #include <stdio.h>
25afb0792fSbostic #include <stdlib.h>
26afb0792fSbostic #include <string.h>
27*168d7fa9Sbostic #include <unistd.h>
2888d53f5dSbill 
29dbf62afdSbostic #define DEF_LEN		4		/* default minimum string length */
30dbf62afdSbostic #define ISSTR(ch)	(isascii(ch) && (isprint(ch) || ch == '\t'))
3188d53f5dSbill 
32dbf62afdSbostic typedef struct exec	EXEC;		/* struct exec cast */
3388d53f5dSbill 
34dbf62afdSbostic static long	foff;			/* offset in the file */
35dbf62afdSbostic static int	hcnt,			/* head count */
36dbf62afdSbostic 		head_len,		/* length of header */
37dbf62afdSbostic 		read_len;		/* length to read */
38dbf62afdSbostic static u_char	hbfr[sizeof(EXEC)];	/* buffer for struct exec */
3988d53f5dSbill 
40afb0792fSbostic static void usage();
41afb0792fSbostic 
main(argc,argv)4288d53f5dSbill main(argc, argv)
4388d53f5dSbill 	int argc;
44dbf62afdSbostic 	char **argv;
4588d53f5dSbill {
46654d9ca0Sbostic 	extern char *optarg;
47654d9ca0Sbostic 	extern int optind;
48654d9ca0Sbostic 	register int ch, cnt;
49654d9ca0Sbostic 	register u_char *C;
50654d9ca0Sbostic 	EXEC *head;
51afb0792fSbostic 	int exitcode, minlen;
52ffb17e88Smarc 	short asdata, oflg, fflg;
53654d9ca0Sbostic 	u_char *bfr;
54afb0792fSbostic 	char *file, *p;
5588d53f5dSbill 
56dbf62afdSbostic 	/*
57dbf62afdSbostic 	 * for backward compatibility, allow '-' to specify 'a' flag; no
58dbf62afdSbostic 	 * longer documented in the man page or usage string.
59dbf62afdSbostic 	 */
60afb0792fSbostic 	asdata = exitcode = fflg = oflg = 0;
61654d9ca0Sbostic 	minlen = -1;
62*168d7fa9Sbostic 	while ((ch = getopt(argc, argv, "-0123456789an:of")) != EOF)
63*168d7fa9Sbostic 		switch (ch) {
64654d9ca0Sbostic 		case '0': case '1': case '2': case '3': case '4':
65654d9ca0Sbostic 		case '5': case '6': case '7': case '8': case '9':
66654d9ca0Sbostic 			/*
67654d9ca0Sbostic 			 * kludge: strings was originally designed to take
68654d9ca0Sbostic 			 * a number after a dash.
69654d9ca0Sbostic 			 */
70654d9ca0Sbostic 			if (minlen == -1) {
71654d9ca0Sbostic 				p = argv[optind - 1];
72654d9ca0Sbostic 				if (p[0] == '-' && p[1] == ch && !p[2])
73654d9ca0Sbostic 					minlen = atoi(++p);
74654d9ca0Sbostic 				else
75654d9ca0Sbostic 					minlen = atoi(argv[optind] + 1);
76654d9ca0Sbostic 			}
77654d9ca0Sbostic 			break;
78654d9ca0Sbostic 		case '-':
7988d53f5dSbill 		case 'a':
80654d9ca0Sbostic 			asdata = 1;
8188d53f5dSbill 			break;
82ffb17e88Smarc 		case 'f':
83ffb17e88Smarc 			fflg = 1;
84ffb17e88Smarc 			break;
85afb0792fSbostic 		case 'n':
86afb0792fSbostic 			minlen = atoi(optarg);
87afb0792fSbostic 			break;
88afb0792fSbostic 		case 'o':
89afb0792fSbostic 			oflg = 1;
90afb0792fSbostic 			break;
91654d9ca0Sbostic 		case '?':
92654d9ca0Sbostic 		default:
93afb0792fSbostic 			usage();
94dbf62afdSbostic 		}
95654d9ca0Sbostic 	argc -= optind;
96654d9ca0Sbostic 	argv += optind;
97654d9ca0Sbostic 
98654d9ca0Sbostic 	if (minlen == -1)
99654d9ca0Sbostic 		minlen = DEF_LEN;
100*168d7fa9Sbostic 	else {
101*168d7fa9Sbostic 		(void)fprintf(stderr, "strings: length less than 1\n");
102*168d7fa9Sbostic 		exit (1);
103*168d7fa9Sbostic 	}
10488d53f5dSbill 
105afb0792fSbostic 	if (!(bfr = malloc((u_int)minlen))) {
106afb0792fSbostic 		(void)fprintf(stderr, "strings: %s\n", strerror(errno));
107654d9ca0Sbostic 		exit(1);
10888d53f5dSbill 	}
109654d9ca0Sbostic 	bfr[minlen] = '\0';
11069dea8ddSbostic 	file = "stdin";
11188d53f5dSbill 	do {
112dbf62afdSbostic 		if (*argv) {
113dbf62afdSbostic 			file = *argv++;
114ffb17e88Smarc 			if (!freopen(file, "r", stdin)) {
115afb0792fSbostic 				(void)fprintf(stderr,
116c017df21Sbostic 				    "strings: %s: %s\n", file, strerror(errno));
117ffb17e88Smarc 				exitcode = 1;
118ffb17e88Smarc 				goto nextfile;
119ffb17e88Smarc 			}
12088d53f5dSbill 		}
121dbf62afdSbostic 		foff = 0;
122ffb17e88Smarc #define DO_EVERYTHING()		{read_len = -1; head_len = 0; goto start;}
123654d9ca0Sbostic 		read_len = -1;
124dbf62afdSbostic 		if (asdata)
125ffb17e88Smarc 			DO_EVERYTHING()
126dbf62afdSbostic 		else {
127dbf62afdSbostic 			head = (EXEC *)hbfr;
128afb0792fSbostic 			if ((head_len =
129afb0792fSbostic 			    read(fileno(stdin), head, sizeof(EXEC))) == -1)
130ffb17e88Smarc 				DO_EVERYTHING()
131dbf62afdSbostic 			if (head_len == sizeof(EXEC) && !N_BADMAG(*head)) {
1321cad0f35Sdonn 				foff = N_TXTOFF(*head);
133afb0792fSbostic 				if (fseek(stdin, foff, SEEK_SET) == -1)
134ffb17e88Smarc 					DO_EVERYTHING()
1351cad0f35Sdonn 				read_len = head->a_text + head->a_data;
136dbf62afdSbostic 				head_len = 0;
137dbf62afdSbostic 			}
138dbf62afdSbostic 			else
139dbf62afdSbostic 				hcnt = 0;
140dbf62afdSbostic 		}
141ffb17e88Smarc start:
142dbf62afdSbostic 		for (cnt = 0; (ch = getch()) != EOF;) {
143dbf62afdSbostic 			if (ISSTR(ch)) {
144dbf62afdSbostic 				if (!cnt)
145dbf62afdSbostic 					C = bfr;
146dbf62afdSbostic 				*C++ = ch;
147dbf62afdSbostic 				if (++cnt < minlen)
14888d53f5dSbill 					continue;
149ffb17e88Smarc 				if (fflg)
150ffb17e88Smarc 					printf("%s:", file);
15188d53f5dSbill 				if (oflg)
152afb0792fSbostic 					printf("%07ld %s",
153afb0792fSbostic 					    foff - minlen, (char *)bfr);
154dbf62afdSbostic 				else
155afb0792fSbostic 					printf("%s", bfr);
156dbf62afdSbostic 				while ((ch = getch()) != EOF && ISSTR(ch))
157dbf62afdSbostic 					putchar((char)ch);
158dbf62afdSbostic 				putchar('\n');
15988d53f5dSbill 			}
160dbf62afdSbostic 			cnt = 0;
16188d53f5dSbill 		}
162ffb17e88Smarc nextfile: ;
163dbf62afdSbostic 	} while (*argv);
164ffb17e88Smarc 	exit(exitcode);
16588d53f5dSbill }
16688d53f5dSbill 
167dbf62afdSbostic /*
168dbf62afdSbostic  * getch --
169dbf62afdSbostic  *	get next character from wherever
170dbf62afdSbostic  */
getch()171dbf62afdSbostic getch()
17288d53f5dSbill {
173dbf62afdSbostic 	++foff;
174dbf62afdSbostic 	if (head_len) {
175dbf62afdSbostic 		if (hcnt < head_len)
176dbf62afdSbostic 			return((int)hbfr[hcnt++]);
177dbf62afdSbostic 		head_len = 0;
17888d53f5dSbill 	}
179654d9ca0Sbostic 	if (read_len == -1 || read_len-- > 0)
180dbf62afdSbostic 		return(getchar());
181dbf62afdSbostic 	return(EOF);
18288d53f5dSbill }
183afb0792fSbostic 
184afb0792fSbostic static void
usage()185afb0792fSbostic usage()
186afb0792fSbostic {
187afb0792fSbostic 	(void)fprintf(stderr,
188afb0792fSbostic 	    "usage: strings [-afo] [-n length] [file ... ]\n");
189afb0792fSbostic 	exit(1);
190afb0792fSbostic }
191