xref: /minix3/usr.bin/cksum/cksum.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: cksum.c,v 1.48 2015/06/16 22:54:10 christos Exp $	*/
2280d8c66SLionel Sambuc 
3280d8c66SLionel Sambuc /*-
4280d8c66SLionel Sambuc  * Copyright (c) 1991, 1993
5280d8c66SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
6280d8c66SLionel Sambuc  *
7280d8c66SLionel Sambuc  * This code is derived from software contributed to Berkeley by
8280d8c66SLionel Sambuc  * James W. Williams of NASA Goddard Space Flight Center.
9280d8c66SLionel Sambuc  *
10280d8c66SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
11280d8c66SLionel Sambuc  * modification, are permitted provided that the following conditions
12280d8c66SLionel Sambuc  * are met:
13280d8c66SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
14280d8c66SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
15280d8c66SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16280d8c66SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17280d8c66SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18280d8c66SLionel Sambuc  * 3. Neither the name of the University nor the names of its contributors
19280d8c66SLionel Sambuc  *    may be used to endorse or promote products derived from this software
20280d8c66SLionel Sambuc  *    without specific prior written permission.
21280d8c66SLionel Sambuc  *
22280d8c66SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23280d8c66SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24280d8c66SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25280d8c66SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26280d8c66SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27280d8c66SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28280d8c66SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29280d8c66SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30280d8c66SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31280d8c66SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32280d8c66SLionel Sambuc  * SUCH DAMAGE.
33280d8c66SLionel Sambuc  */
34280d8c66SLionel Sambuc 
35280d8c66SLionel Sambuc /*-
36280d8c66SLionel Sambuc  * Copyright (c) 1997 Jason R. Thorpe.  All rights reserved.
37280d8c66SLionel Sambuc  *
38280d8c66SLionel Sambuc  * This code is derived from software contributed to Berkeley by
39280d8c66SLionel Sambuc  * James W. Williams of NASA Goddard Space Flight Center.
40280d8c66SLionel Sambuc  *
41280d8c66SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
42280d8c66SLionel Sambuc  * modification, are permitted provided that the following conditions
43280d8c66SLionel Sambuc  * are met:
44280d8c66SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
45280d8c66SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
46280d8c66SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
47280d8c66SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
48280d8c66SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
49280d8c66SLionel Sambuc  * 3. All advertising materials mentioning features or use of this software
50280d8c66SLionel Sambuc  *    must display the following acknowledgement:
51280d8c66SLionel Sambuc  *	This product includes software developed by the University of
52280d8c66SLionel Sambuc  *	California, Berkeley and its contributors.
53280d8c66SLionel Sambuc  * 4. Neither the name of the University nor the names of its contributors
54280d8c66SLionel Sambuc  *    may be used to endorse or promote products derived from this software
55280d8c66SLionel Sambuc  *    without specific prior written permission.
56280d8c66SLionel Sambuc  *
57280d8c66SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58280d8c66SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59280d8c66SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60280d8c66SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61280d8c66SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62280d8c66SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63280d8c66SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64280d8c66SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65280d8c66SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66280d8c66SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67280d8c66SLionel Sambuc  * SUCH DAMAGE.
68280d8c66SLionel Sambuc  */
69280d8c66SLionel Sambuc 
70280d8c66SLionel Sambuc #if HAVE_NBTOOL_CONFIG_H
71280d8c66SLionel Sambuc #include "nbtool_config.h"
72280d8c66SLionel Sambuc #endif
73280d8c66SLionel Sambuc 
74280d8c66SLionel Sambuc #include <sys/cdefs.h>
75280d8c66SLionel Sambuc #if defined(__COPYRIGHT) && !defined(lint)
76280d8c66SLionel Sambuc __COPYRIGHT("@(#) Copyright (c) 1991, 1993\
77280d8c66SLionel Sambuc  The Regents of the University of California.  All rights reserved.");
78280d8c66SLionel Sambuc #endif /* not lint */
79280d8c66SLionel Sambuc 
80280d8c66SLionel Sambuc #if defined(__RCSID) && !defined(lint)
81280d8c66SLionel Sambuc #if 0
82280d8c66SLionel Sambuc static char sccsid[] = "@(#)cksum.c	8.2 (Berkeley) 4/28/95";
83280d8c66SLionel Sambuc #endif
84*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: cksum.c,v 1.48 2015/06/16 22:54:10 christos Exp $");
85280d8c66SLionel Sambuc #endif /* not lint */
86280d8c66SLionel Sambuc 
87280d8c66SLionel Sambuc #include <sys/types.h>
88280d8c66SLionel Sambuc 
89280d8c66SLionel Sambuc #include <ctype.h>
90280d8c66SLionel Sambuc #include <err.h>
91280d8c66SLionel Sambuc #include <errno.h>
92280d8c66SLionel Sambuc #include <fcntl.h>
93280d8c66SLionel Sambuc #include <locale.h>
94280d8c66SLionel Sambuc #include <md2.h>
95280d8c66SLionel Sambuc #include <md4.h>
96280d8c66SLionel Sambuc #include <md5.h>
97280d8c66SLionel Sambuc #include <rmd160.h>
98280d8c66SLionel Sambuc #include <sha1.h>
99280d8c66SLionel Sambuc #include <sha2.h>
100280d8c66SLionel Sambuc #include <stdio.h>
101280d8c66SLionel Sambuc #include <stdlib.h>
102280d8c66SLionel Sambuc #include <string.h>
103280d8c66SLionel Sambuc #include <unistd.h>
104280d8c66SLionel Sambuc 
105280d8c66SLionel Sambuc #include "extern.h"
106280d8c66SLionel Sambuc 
107*0a6a1f1dSLionel Sambuc #define PRINT_NORMAL     0x01
108*0a6a1f1dSLionel Sambuc #define PRINT_QUIET      0x02
109*0a6a1f1dSLionel Sambuc 
110280d8c66SLionel Sambuc typedef char *(*_filefunc)(const char *, char *);
111280d8c66SLionel Sambuc 
112280d8c66SLionel Sambuc const struct hash {
113280d8c66SLionel Sambuc 	const char *progname;
114280d8c66SLionel Sambuc 	const char *hashname;
115280d8c66SLionel Sambuc 	void (*stringfunc)(const char *);
116280d8c66SLionel Sambuc 	void (*timetrialfunc)(void);
117280d8c66SLionel Sambuc 	void (*testsuitefunc)(void);
118280d8c66SLionel Sambuc 	void (*filterfunc)(int);
119280d8c66SLionel Sambuc 	char *(*filefunc)(const char *, char *);
120280d8c66SLionel Sambuc } hashes[] = {
121280d8c66SLionel Sambuc 	{ "md2", "MD2",
122280d8c66SLionel Sambuc 	  MD2String, MD2TimeTrial, MD2TestSuite,
123280d8c66SLionel Sambuc 	  MD2Filter, MD2File },
124280d8c66SLionel Sambuc 	{ "md4", "MD4",
125280d8c66SLionel Sambuc 	  MD4String, MD4TimeTrial, MD4TestSuite,
126280d8c66SLionel Sambuc 	  MD4Filter, MD4File },
127280d8c66SLionel Sambuc 	{ "md5", "MD5",
128280d8c66SLionel Sambuc 	  MD5String, MD5TimeTrial, MD5TestSuite,
129280d8c66SLionel Sambuc 	  MD5Filter, MD5File },
130280d8c66SLionel Sambuc 	{ "rmd160", "RMD160",
131280d8c66SLionel Sambuc 	  RMD160String, RMD160TimeTrial, RMD160TestSuite,
132280d8c66SLionel Sambuc 	  RMD160Filter, (_filefunc) RMD160File },
133280d8c66SLionel Sambuc 	{ "sha1", "SHA1",
134280d8c66SLionel Sambuc 	  SHA1String, SHA1TimeTrial, SHA1TestSuite,
135280d8c66SLionel Sambuc 	  SHA1Filter, (_filefunc) SHA1File },
136280d8c66SLionel Sambuc 	{ "sha256", "SHA256",
137280d8c66SLionel Sambuc 	  SHA256_String, SHA256_TimeTrial, SHA256_TestSuite,
138280d8c66SLionel Sambuc 	  SHA256_Filter, (_filefunc) SHA256_File },
139280d8c66SLionel Sambuc 	{ "sha384", "SHA384",
140280d8c66SLionel Sambuc 	  SHA384_String, SHA384_TimeTrial, SHA384_TestSuite,
141280d8c66SLionel Sambuc 	  SHA384_Filter, (_filefunc) SHA384_File },
142280d8c66SLionel Sambuc 	{ "sha512", "SHA512",
143280d8c66SLionel Sambuc 	  SHA512_String, SHA512_TimeTrial, SHA512_TestSuite,
144280d8c66SLionel Sambuc 	  SHA512_Filter, (_filefunc) SHA512_File },
145280d8c66SLionel Sambuc 	{ .progname = NULL, },
146280d8c66SLionel Sambuc };
147280d8c66SLionel Sambuc 
148280d8c66SLionel Sambuc static int	hash_digest_file(char *, const struct hash *, int);
149280d8c66SLionel Sambuc __dead static void	requirehash(const char *);
150280d8c66SLionel Sambuc __dead static void	usage(void);
151280d8c66SLionel Sambuc 
152280d8c66SLionel Sambuc int
main(int argc,char ** argv)153280d8c66SLionel Sambuc main(int argc, char **argv)
154280d8c66SLionel Sambuc {
15584d9c625SLionel Sambuc 	int ch, fd, rval, pflag, nohashstdin;
156280d8c66SLionel Sambuc 	u_int32_t val;
157280d8c66SLionel Sambuc 	off_t len;
158280d8c66SLionel Sambuc 	char *fn;
159280d8c66SLionel Sambuc 	const char *progname;
160280d8c66SLionel Sambuc 	int (*cfncn) (int, u_int32_t *, off_t *);
161280d8c66SLionel Sambuc 	void (*pfncn) (char *, u_int32_t, off_t);
162280d8c66SLionel Sambuc 	const struct hash *hash;
163*0a6a1f1dSLionel Sambuc 	int i, check_warn, do_check;
164*0a6a1f1dSLionel Sambuc 	int print_flags;
165280d8c66SLionel Sambuc 
166280d8c66SLionel Sambuc 	cfncn = NULL;
167280d8c66SLionel Sambuc 	pfncn = NULL;
16884d9c625SLionel Sambuc 	pflag = nohashstdin = 0;
169280d8c66SLionel Sambuc 	check_warn = 0;
170280d8c66SLionel Sambuc 	do_check = 0;
171*0a6a1f1dSLionel Sambuc 	print_flags = 0;
172280d8c66SLionel Sambuc 
173280d8c66SLionel Sambuc 	setlocale(LC_ALL, "");
174280d8c66SLionel Sambuc 
175280d8c66SLionel Sambuc 	progname = getprogname();
176280d8c66SLionel Sambuc 
177280d8c66SLionel Sambuc 	for (hash = hashes; hash->hashname != NULL; hash++)
178280d8c66SLionel Sambuc 		if (strcmp(progname, hash->progname) == 0)
179280d8c66SLionel Sambuc 			break;
180280d8c66SLionel Sambuc 
181280d8c66SLionel Sambuc 	if (hash->hashname == NULL) {
182280d8c66SLionel Sambuc 		hash = NULL;
183280d8c66SLionel Sambuc 
184280d8c66SLionel Sambuc 		if (!strcmp(progname, "sum")) {
185280d8c66SLionel Sambuc 			cfncn = csum1;
186280d8c66SLionel Sambuc 			pfncn = psum1;
187280d8c66SLionel Sambuc 		} else {
188280d8c66SLionel Sambuc 			cfncn = crc;
189280d8c66SLionel Sambuc 			pfncn = pcrc;
190280d8c66SLionel Sambuc 		}
191280d8c66SLionel Sambuc 	}
192280d8c66SLionel Sambuc 
193*0a6a1f1dSLionel Sambuc 	while ((ch = getopt(argc, argv, "a:cno:pqs:twx")) != -1)
194280d8c66SLionel Sambuc 		switch(ch) {
195280d8c66SLionel Sambuc 		case 'a':
196280d8c66SLionel Sambuc 			if (hash) {
197*0a6a1f1dSLionel Sambuc 				warnx("illegal use of -a option");
198280d8c66SLionel Sambuc 				usage();
199280d8c66SLionel Sambuc 			}
200280d8c66SLionel Sambuc 			i = 0;
201280d8c66SLionel Sambuc 			while (hashes[i].hashname != NULL) {
202280d8c66SLionel Sambuc 				if (!strcasecmp(hashes[i].hashname, optarg)) {
203280d8c66SLionel Sambuc 					hash = &hashes[i];
204280d8c66SLionel Sambuc 					break;
205280d8c66SLionel Sambuc 				}
206280d8c66SLionel Sambuc 				i++;
207280d8c66SLionel Sambuc 			}
208280d8c66SLionel Sambuc 			if (hash == NULL) {
209280d8c66SLionel Sambuc 				if (!strcasecmp(optarg, "old1")) {
210280d8c66SLionel Sambuc 					cfncn = csum1;
211280d8c66SLionel Sambuc 					pfncn = psum1;
212280d8c66SLionel Sambuc 				} else if (!strcasecmp(optarg, "old2")) {
213280d8c66SLionel Sambuc 					cfncn = csum2;
214280d8c66SLionel Sambuc 					pfncn = psum2;
215280d8c66SLionel Sambuc 				} else if (!strcasecmp(optarg, "crc")) {
216280d8c66SLionel Sambuc 					cfncn = crc;
217280d8c66SLionel Sambuc 					pfncn = pcrc;
218280d8c66SLionel Sambuc 				} else {
219280d8c66SLionel Sambuc 					warnx("illegal argument to -a option");
220280d8c66SLionel Sambuc 					usage();
221280d8c66SLionel Sambuc 				}
222280d8c66SLionel Sambuc 			}
223280d8c66SLionel Sambuc 			break;
224280d8c66SLionel Sambuc 		case 'c':
225280d8c66SLionel Sambuc 			do_check = 1;
226280d8c66SLionel Sambuc 			break;
227280d8c66SLionel Sambuc 		case 'n':
228*0a6a1f1dSLionel Sambuc 			print_flags |= PRINT_NORMAL;
229280d8c66SLionel Sambuc 			break;
230280d8c66SLionel Sambuc 		case 'o':
231280d8c66SLionel Sambuc 			if (hash) {
232280d8c66SLionel Sambuc 				warnx("%s mutually exclusive with sum",
233280d8c66SLionel Sambuc 				      hash->hashname);
234280d8c66SLionel Sambuc 				usage();
235280d8c66SLionel Sambuc 			}
236280d8c66SLionel Sambuc 			if (!strcmp(optarg, "1")) {
237280d8c66SLionel Sambuc 				cfncn = csum1;
238280d8c66SLionel Sambuc 				pfncn = psum1;
239280d8c66SLionel Sambuc 			} else if (!strcmp(optarg, "2")) {
240280d8c66SLionel Sambuc 				cfncn = csum2;
241280d8c66SLionel Sambuc 				pfncn = psum2;
242280d8c66SLionel Sambuc 			} else {
243280d8c66SLionel Sambuc 				warnx("illegal argument to -o option");
244280d8c66SLionel Sambuc 				usage();
245280d8c66SLionel Sambuc 			}
246280d8c66SLionel Sambuc 			break;
247280d8c66SLionel Sambuc 		case 'p':
248280d8c66SLionel Sambuc 			if (hash == NULL)
249280d8c66SLionel Sambuc 				requirehash("-p");
250280d8c66SLionel Sambuc 			pflag = 1;
251280d8c66SLionel Sambuc 			break;
252*0a6a1f1dSLionel Sambuc 		case 'q':
253*0a6a1f1dSLionel Sambuc 			print_flags |= PRINT_QUIET;
254*0a6a1f1dSLionel Sambuc 			break;
255280d8c66SLionel Sambuc 		case 's':
256280d8c66SLionel Sambuc 			if (hash == NULL)
257280d8c66SLionel Sambuc 				requirehash("-s");
258280d8c66SLionel Sambuc 			nohashstdin = 1;
259280d8c66SLionel Sambuc 			hash->stringfunc(optarg);
260280d8c66SLionel Sambuc 			break;
261280d8c66SLionel Sambuc 		case 't':
262280d8c66SLionel Sambuc 			if (hash == NULL)
263280d8c66SLionel Sambuc 				requirehash("-t");
264280d8c66SLionel Sambuc 			nohashstdin = 1;
265280d8c66SLionel Sambuc 			hash->timetrialfunc();
266280d8c66SLionel Sambuc 			break;
267280d8c66SLionel Sambuc 		case 'w':
268280d8c66SLionel Sambuc 			check_warn = 1;
269280d8c66SLionel Sambuc 			break;
270280d8c66SLionel Sambuc 		case 'x':
271280d8c66SLionel Sambuc 			if (hash == NULL)
272280d8c66SLionel Sambuc 				requirehash("-x");
273280d8c66SLionel Sambuc 			nohashstdin = 1;
274280d8c66SLionel Sambuc 			hash->testsuitefunc();
275280d8c66SLionel Sambuc 			break;
276280d8c66SLionel Sambuc 		case '?':
277280d8c66SLionel Sambuc 		default:
278280d8c66SLionel Sambuc 			usage();
279280d8c66SLionel Sambuc 		}
280280d8c66SLionel Sambuc 	argc -= optind;
281280d8c66SLionel Sambuc 	argv += optind;
282280d8c66SLionel Sambuc 
283280d8c66SLionel Sambuc 	if (do_check) {
284280d8c66SLionel Sambuc 		/*
285280d8c66SLionel Sambuc 		 * Verify checksums
286280d8c66SLionel Sambuc 		 */
287280d8c66SLionel Sambuc 		FILE *f;
288280d8c66SLionel Sambuc 		char buf[BUFSIZ];
289280d8c66SLionel Sambuc 		char *s, *p_filename, *p_cksum;
290280d8c66SLionel Sambuc 		int l_filename, l_cksum;
291280d8c66SLionel Sambuc 		char filename[BUFSIZ];
292280d8c66SLionel Sambuc 		char cksum[BUFSIZ];
293280d8c66SLionel Sambuc 		int ok,cnt,badcnt;
294280d8c66SLionel Sambuc 
295280d8c66SLionel Sambuc 		rval = 0;
296280d8c66SLionel Sambuc 		cnt = badcnt = 0;
297280d8c66SLionel Sambuc 
298280d8c66SLionel Sambuc 		if (argc == 0) {
299280d8c66SLionel Sambuc 			f = fdopen(STDIN_FILENO, "r");
300280d8c66SLionel Sambuc 		} else {
301280d8c66SLionel Sambuc 			f = fopen(argv[0], "r");
302280d8c66SLionel Sambuc 		}
303280d8c66SLionel Sambuc 		if (f == NULL)
304280d8c66SLionel Sambuc 			err(1, "Cannot read %s",
305280d8c66SLionel Sambuc 			    argc>0?argv[0]:"stdin");
306280d8c66SLionel Sambuc 
307280d8c66SLionel Sambuc 		while(fgets(buf, sizeof(buf), f) != NULL) {
308280d8c66SLionel Sambuc 			s = strrchr(buf, '\n');
309280d8c66SLionel Sambuc 			if (s)
310280d8c66SLionel Sambuc 				*s = '\0';
311280d8c66SLionel Sambuc 
312280d8c66SLionel Sambuc 			p_cksum = p_filename = NULL;
313280d8c66SLionel Sambuc 
314280d8c66SLionel Sambuc 			p_filename = strchr(buf, '(');
315280d8c66SLionel Sambuc 			if (p_filename) {
316280d8c66SLionel Sambuc 				/*
317280d8c66SLionel Sambuc 				 * Assume 'normal' output if there's a '('
318280d8c66SLionel Sambuc 				 */
319280d8c66SLionel Sambuc 				p_filename += 1;
320*0a6a1f1dSLionel Sambuc 				print_flags &= ~(PRINT_NORMAL);
321280d8c66SLionel Sambuc 
322280d8c66SLionel Sambuc 				p_cksum = strrchr(p_filename, ')');
323280d8c66SLionel Sambuc 				if (p_cksum == NULL) {
324280d8c66SLionel Sambuc 					if (check_warn)
325280d8c66SLionel Sambuc 						warnx("bogus format: %s. "
326280d8c66SLionel Sambuc 						      "Skipping...",
327280d8c66SLionel Sambuc 						      buf);
328280d8c66SLionel Sambuc 					rval = 1;
329280d8c66SLionel Sambuc 					continue;
330280d8c66SLionel Sambuc 				}
331280d8c66SLionel Sambuc  				p_cksum += 4;
332280d8c66SLionel Sambuc 
333280d8c66SLionel Sambuc 				l_cksum = strlen(p_cksum);
334280d8c66SLionel Sambuc 				l_filename = p_cksum - p_filename - 4;
335280d8c66SLionel Sambuc 
336280d8c66SLionel Sambuc 				/* Sanity check, and find proper hash if
337280d8c66SLionel Sambuc 				 * it's not the same as the current program
338280d8c66SLionel Sambuc 				 */
339280d8c66SLionel Sambuc 				if (hash == NULL ||
340280d8c66SLionel Sambuc 				    strncmp(buf, hash->hashname,
341280d8c66SLionel Sambuc 					    strlen(hash->hashname)) != 0) {
342280d8c66SLionel Sambuc 					/*
343280d8c66SLionel Sambuc 					 * Search proper hash
344280d8c66SLionel Sambuc 					 */
345280d8c66SLionel Sambuc 					const struct hash *nhash;
346280d8c66SLionel Sambuc 
347280d8c66SLionel Sambuc 					for (nhash = hashes ;
348280d8c66SLionel Sambuc 					     nhash->hashname != NULL;
349280d8c66SLionel Sambuc 					     nhash++)
350280d8c66SLionel Sambuc 						if (strncmp(buf,
351280d8c66SLionel Sambuc 							    nhash->hashname,
352280d8c66SLionel Sambuc 							    strlen(nhash->hashname)) == 0)
353280d8c66SLionel Sambuc 							break;
354280d8c66SLionel Sambuc 
355280d8c66SLionel Sambuc 
356280d8c66SLionel Sambuc 					if (nhash->hashname == NULL) {
357280d8c66SLionel Sambuc 						if (check_warn)
358280d8c66SLionel Sambuc 							warnx("unknown hash: %s",
359280d8c66SLionel Sambuc 							      buf);
360280d8c66SLionel Sambuc 						rval = 1;
361280d8c66SLionel Sambuc 						continue;
362280d8c66SLionel Sambuc 					} else {
363280d8c66SLionel Sambuc 						hash = nhash;
364280d8c66SLionel Sambuc 					}
365280d8c66SLionel Sambuc 				}
366280d8c66SLionel Sambuc 
367280d8c66SLionel Sambuc 			} else {
368280d8c66SLionel Sambuc 				if (hash) {
369280d8c66SLionel Sambuc 					int nspaces;
370280d8c66SLionel Sambuc 
371280d8c66SLionel Sambuc 					/*
372280d8c66SLionel Sambuc 					 * 'normal' output, no (ck)sum
373280d8c66SLionel Sambuc 					 */
374*0a6a1f1dSLionel Sambuc 					print_flags |= PRINT_NORMAL;
375280d8c66SLionel Sambuc 					nspaces = 1;
376280d8c66SLionel Sambuc 
377280d8c66SLionel Sambuc 					p_cksum = buf;
378280d8c66SLionel Sambuc 					p_filename = strchr(buf, ' ');
379280d8c66SLionel Sambuc 					if (p_filename == NULL) {
380280d8c66SLionel Sambuc 						if (check_warn)
381280d8c66SLionel Sambuc 							warnx("no filename in %s? "
382280d8c66SLionel Sambuc 							      "Skipping...", buf);
383280d8c66SLionel Sambuc 						rval = 1;
384280d8c66SLionel Sambuc 						continue;
385280d8c66SLionel Sambuc 					}
386280d8c66SLionel Sambuc 					while (isspace((int)*++p_filename))
387280d8c66SLionel Sambuc 						nspaces++;
388280d8c66SLionel Sambuc 					l_filename = strlen(p_filename);
389280d8c66SLionel Sambuc 					l_cksum = p_filename - buf - nspaces;
390280d8c66SLionel Sambuc 				} else {
391280d8c66SLionel Sambuc 					/*
392280d8c66SLionel Sambuc 					 * sum/cksum output format
393280d8c66SLionel Sambuc 					 */
394280d8c66SLionel Sambuc 					p_cksum = buf;
395280d8c66SLionel Sambuc 					s=strchr(p_cksum, ' ');
396280d8c66SLionel Sambuc 					if (s == NULL) {
397280d8c66SLionel Sambuc 						if (check_warn)
398280d8c66SLionel Sambuc 							warnx("bogus format: %s."
399280d8c66SLionel Sambuc 							      " Skipping...",
400280d8c66SLionel Sambuc 							      buf);
401280d8c66SLionel Sambuc 						rval = 1;
402280d8c66SLionel Sambuc 						continue;
403280d8c66SLionel Sambuc 					}
404280d8c66SLionel Sambuc 					l_cksum = s - p_cksum;
405280d8c66SLionel Sambuc 
406280d8c66SLionel Sambuc 					p_filename = strrchr(buf, ' ');
407280d8c66SLionel Sambuc 					if (p_filename == NULL) {
408280d8c66SLionel Sambuc 						if (check_warn)
409280d8c66SLionel Sambuc 							warnx("no filename in %s?"
410280d8c66SLionel Sambuc 							      " Skipping...",
411280d8c66SLionel Sambuc 							      buf);
412280d8c66SLionel Sambuc 						rval = 1;
413280d8c66SLionel Sambuc 						continue;
414280d8c66SLionel Sambuc 					}
415280d8c66SLionel Sambuc 					p_filename++;
416280d8c66SLionel Sambuc 					l_filename = strlen(p_filename);
417280d8c66SLionel Sambuc 				}
418280d8c66SLionel Sambuc 			}
419280d8c66SLionel Sambuc 
420280d8c66SLionel Sambuc 			strlcpy(filename, p_filename, l_filename+1);
421280d8c66SLionel Sambuc 			strlcpy(cksum, p_cksum, l_cksum+1);
422280d8c66SLionel Sambuc 
423280d8c66SLionel Sambuc 			if (hash) {
424280d8c66SLionel Sambuc 				if (access(filename, R_OK) == 0
425280d8c66SLionel Sambuc 				    && strcmp(cksum, hash->filefunc(filename, NULL)) == 0)
426280d8c66SLionel Sambuc 					ok = 1;
427280d8c66SLionel Sambuc 				else
428280d8c66SLionel Sambuc 					ok = 0;
429280d8c66SLionel Sambuc 			} else {
430280d8c66SLionel Sambuc 				if ((fd = open(filename, O_RDONLY, 0)) < 0) {
431280d8c66SLionel Sambuc 					if (check_warn)
432280d8c66SLionel Sambuc 						warn("%s", filename);
433280d8c66SLionel Sambuc 					rval = 1;
434280d8c66SLionel Sambuc 					ok = 0;
435280d8c66SLionel Sambuc 				} else {
436280d8c66SLionel Sambuc 					if (cfncn(fd, &val, &len))
437280d8c66SLionel Sambuc 						ok = 0;
438280d8c66SLionel Sambuc 					else {
439280d8c66SLionel Sambuc 						u_int32_t should_val;
440280d8c66SLionel Sambuc 
441280d8c66SLionel Sambuc 						should_val =
442280d8c66SLionel Sambuc 						  strtoul(cksum, NULL, 10);
443280d8c66SLionel Sambuc 						if (val == should_val)
444280d8c66SLionel Sambuc 							ok = 1;
445280d8c66SLionel Sambuc 						else
446280d8c66SLionel Sambuc 							ok = 0;
447280d8c66SLionel Sambuc 					}
448280d8c66SLionel Sambuc 					close(fd);
449280d8c66SLionel Sambuc 				}
450280d8c66SLionel Sambuc 			}
451280d8c66SLionel Sambuc 
452280d8c66SLionel Sambuc 			if (! ok) {
453280d8c66SLionel Sambuc 				if (hash)
454280d8c66SLionel Sambuc 					printf("(%s) ", hash->hashname);
455280d8c66SLionel Sambuc 				printf("%s: FAILED\n", filename);
456280d8c66SLionel Sambuc 				badcnt++;
457280d8c66SLionel Sambuc 			}
458280d8c66SLionel Sambuc 			cnt++;
459280d8c66SLionel Sambuc 
460280d8c66SLionel Sambuc 		}
461280d8c66SLionel Sambuc 		fclose(f);
462280d8c66SLionel Sambuc 
463280d8c66SLionel Sambuc 		if (badcnt > 0)
464280d8c66SLionel Sambuc 			rval = 1;
465280d8c66SLionel Sambuc 
466280d8c66SLionel Sambuc 	} else {
467280d8c66SLionel Sambuc 		/*
468280d8c66SLionel Sambuc 		 * Calculate checksums
469280d8c66SLionel Sambuc 		 */
470280d8c66SLionel Sambuc 
471280d8c66SLionel Sambuc 		fd = STDIN_FILENO;
472280d8c66SLionel Sambuc 		fn = NULL;
473280d8c66SLionel Sambuc 		rval = 0;
474280d8c66SLionel Sambuc 		do {
475280d8c66SLionel Sambuc 			if (*argv) {
476280d8c66SLionel Sambuc 				fn = *argv++;
477280d8c66SLionel Sambuc 				if (hash != NULL) {
478*0a6a1f1dSLionel Sambuc 					if (hash_digest_file(fn, hash, print_flags)) {
479280d8c66SLionel Sambuc 						warn("%s", fn);
480280d8c66SLionel Sambuc 						rval = 1;
481280d8c66SLionel Sambuc 					}
482280d8c66SLionel Sambuc 					continue;
483280d8c66SLionel Sambuc 				}
484280d8c66SLionel Sambuc 				if ((fd = open(fn, O_RDONLY, 0)) < 0) {
485280d8c66SLionel Sambuc 					warn("%s", fn);
486280d8c66SLionel Sambuc 					rval = 1;
487280d8c66SLionel Sambuc 					continue;
488280d8c66SLionel Sambuc 				}
489280d8c66SLionel Sambuc 			} else if (hash && !nohashstdin) {
490280d8c66SLionel Sambuc 				hash->filterfunc(pflag);
491280d8c66SLionel Sambuc 			}
492280d8c66SLionel Sambuc 
493280d8c66SLionel Sambuc 			if (hash == NULL) {
494280d8c66SLionel Sambuc 				if (cfncn(fd, &val, &len)) {
495280d8c66SLionel Sambuc 					warn("%s", fn ? fn : "stdin");
496280d8c66SLionel Sambuc 					rval = 1;
497280d8c66SLionel Sambuc 				} else
498280d8c66SLionel Sambuc 					pfncn(fn, val, len);
499280d8c66SLionel Sambuc 				(void)close(fd);
500280d8c66SLionel Sambuc 			}
501280d8c66SLionel Sambuc 		} while (*argv);
502280d8c66SLionel Sambuc 	}
503280d8c66SLionel Sambuc 	exit(rval);
504280d8c66SLionel Sambuc }
505280d8c66SLionel Sambuc 
506280d8c66SLionel Sambuc static int
hash_digest_file(char * fn,const struct hash * hash,int flags)507*0a6a1f1dSLionel Sambuc hash_digest_file(char *fn, const struct hash *hash, int flags)
508280d8c66SLionel Sambuc {
509280d8c66SLionel Sambuc 	char *cp;
510280d8c66SLionel Sambuc 
511280d8c66SLionel Sambuc 	cp = hash->filefunc(fn, NULL);
512280d8c66SLionel Sambuc 	if (cp == NULL)
513280d8c66SLionel Sambuc 		return 1;
514280d8c66SLionel Sambuc 
515*0a6a1f1dSLionel Sambuc 	if (flags & PRINT_QUIET)
516*0a6a1f1dSLionel Sambuc 		printf("%s\n", cp);
517*0a6a1f1dSLionel Sambuc 	else if (flags & PRINT_NORMAL)
518280d8c66SLionel Sambuc 		printf("%s %s\n", cp, fn);
519280d8c66SLionel Sambuc 	else
520280d8c66SLionel Sambuc 		printf("%s (%s) = %s\n", hash->hashname, fn, cp);
521280d8c66SLionel Sambuc 
522280d8c66SLionel Sambuc 	free(cp);
523280d8c66SLionel Sambuc 
524280d8c66SLionel Sambuc 	return 0;
525280d8c66SLionel Sambuc }
526280d8c66SLionel Sambuc 
527280d8c66SLionel Sambuc static void
requirehash(const char * flg)528280d8c66SLionel Sambuc requirehash(const char *flg)
529280d8c66SLionel Sambuc {
530280d8c66SLionel Sambuc 	warnx("%s flag requires `-a algorithm'", flg);
531280d8c66SLionel Sambuc 	usage();
532280d8c66SLionel Sambuc }
533280d8c66SLionel Sambuc 
534280d8c66SLionel Sambuc static void
usage(void)535280d8c66SLionel Sambuc usage(void)
536280d8c66SLionel Sambuc {
537280d8c66SLionel Sambuc 	const char fileargs[] = "[file ... | -c [-w] [sumfile]]";
538280d8c66SLionel Sambuc 	const char sumargs[] = "[-n] [-a algorithm [-ptx] [-s string]] [-o 1|2]";
539280d8c66SLionel Sambuc 	const char hashargs[] = "[-nptx] [-s string]";
540280d8c66SLionel Sambuc 
541280d8c66SLionel Sambuc 	(void)fprintf(stderr, "usage: cksum %s\n             %s\n",
542280d8c66SLionel Sambuc 	    sumargs, fileargs);
543280d8c66SLionel Sambuc 	(void)fprintf(stderr, "       sum %s\n           %s\n",
544280d8c66SLionel Sambuc 	    sumargs, fileargs);
545280d8c66SLionel Sambuc 	(void)fprintf(stderr, "       md2 %s %s\n", hashargs, fileargs);
546280d8c66SLionel Sambuc 	(void)fprintf(stderr, "       md4 %s %s\n", hashargs, fileargs);
547280d8c66SLionel Sambuc 	(void)fprintf(stderr, "       md5 %s %s\n", hashargs, fileargs);
548280d8c66SLionel Sambuc 	(void)fprintf(stderr, "       rmd160 %s %s\n", hashargs, fileargs);
549280d8c66SLionel Sambuc 	(void)fprintf(stderr, "       sha1 %s %s\n", hashargs, fileargs);
550280d8c66SLionel Sambuc 	exit(1);
551280d8c66SLionel Sambuc }
552