bbe820c4082c4316bbf36f9084cc95c8fd5f4803
[skeinsum.git] / skein_cli.c
1 /* Copyright (C) 2014 2015 Jason Self <j@jxself.org>
2
3 This file is part of skeinsum.
4
5 skeinsum is free software: you can redistribute it and/or modify it 
6 under the terms of the GNU General Public License as published by 
7 the Free Software Foundation, either version 3 of the License, or 
8 (at your option) any later version.
9
10 skeinsum is distributed in the hope that it will be useful, but 
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with skeinsum. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "config.h"
20
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <dirent.h>
26 #include <getopt.h>
27 #include <malloc.h>
28 #include <math.h>
29 #include <glob.h>
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include "SHA3api_ref.h"
33
34 extern const int hashbitlen;
35
36 #define MaxNmberFiles 10
37 #define skeinVersion "1.3"
38 const size_t input_minbufsize = 32 * 1024;
39 const size_t input_maxbufsize = 32 * 1024 * 1024;
40
41
42 char invalidOption = 0;
43
44 enum
45 {
46   QUIET_OPTION = 11,
47   STATUS_OPTION,
48   TAG_OPTION,
49   HELP_OPTION,
50   VERSION_OPTION
51 };
52
53 static struct option const long_options[] =
54 {
55   { "binary", no_argument, NULL, 'b' },
56   { "check", no_argument, NULL, 'c' },
57   { "quiet", no_argument, NULL, QUIET_OPTION },
58   { "status", no_argument, NULL, STATUS_OPTION },
59   { "text", no_argument, NULL, 't' },
60   { "warn", no_argument, NULL, 'w' },
61   { "tag", no_argument, NULL, TAG_OPTION },
62   { "help", no_argument, NULL, HELP_OPTION },
63   { "version", no_argument, NULL, VERSION_OPTION },
64   { NULL, 0, NULL, 0 }
65 };
66
67 void printHexMsg(unsigned char *ptr, int size, char result[])
68 {
69         int i = 0;
70         int j = 0;
71         char High, Low;
72         for (i = 0 ; i < size ; i ++)
73         {
74                 High = ptr[i]>>4;
75                 Low = ptr[i]&0x0F;
76
77                 if (High >= 0xA && High <= 0xF)
78                         High += 0x37;
79                 else if(High >= 0x0 && High <= 0x9)
80                         High += 0x30;
81
82                 if (Low >= 0xA && Low <= 0xF)
83                         Low += 0x37;
84                 else if(Low >= 0x0 && Low <= 0x9)
85                         Low += 0x30;
86
87                 result[j++] = High;
88                 result[j++] = Low;
89         }
90         result[i] = 0;
91 }
92
93 int HashWithMode(char file_name[], char MsgDigest[], char mode)
94 {
95         /* Try to get file info */
96         struct stat st;
97         if (stat(file_name, &st) < 0) {
98                 printf("skein%dsum: %s: STAT FAILED: %s\n", hashbitlen, file_name, strerror(errno));
99                 return -1;
100         }
101
102         /* Get filesize */
103         size_t fsize = st.st_size;
104         if (fsize != st.st_size) {
105                 printf("skein%dsum: %s: SIZE WARNING: filesize %llu is too big for reading into memory!\n",
106                         hashbitlen, file_name, (long long unsigned)st.st_size);
107         }
108
109         /* Open file */
110         FILE *fp_in = fopen(file_name, (mode == 't' ? "r" : "rb") );
111         if (!fp_in) {
112                 printf("skein%dsum: %s: OPEN FAILED: %s\n", hashbitlen, file_name, strerror(errno));
113                 return -1;
114         }
115
116         /* Allocate buffer */
117         size_t bufsize = fsize + 1;
118         if (bufsize < input_minbufsize)
119                 bufsize = input_minbufsize;
120
121         char *readbuf = malloc (bufsize);
122         if (!readbuf && bufsize > input_maxbufsize) {  /* ..Try to get contents by smaller portions */
123                 bufsize = input_maxbufsize;
124                 readbuf = malloc (bufsize);
125         }
126
127         if (!readbuf) {
128                 printf("skein%dsum: %s: MEM FAILED: %s\n", hashbitlen, file_name, strerror(errno));
129                 fclose(fp_in);
130                 return -1;
131         }
132
133         /* Read contents */
134         size_t readpos = 0, readed, total_readed = 0;
135
136         while (1) {
137                 size_t maxread = bufsize - readpos;
138                 readed = fread(readbuf, 1, maxread, fp_in);
139                 if (readed > 0 && readed <= maxread)
140                         total_readed += readed;
141                 if (readed != maxread)
142                         break;
143                 if (getenv("SKEIN_DEBUG"))
144                         printf("DEBUG: bufsize=%u (0x%x), readpos=%u (0x%x), maxread=%u (0x%x), total=%u (0x%x)\n",
145                                 bufsize, bufsize, readpos, readpos, maxread, maxread, total_readed, total_readed);
146                 char *newbuf = NULL;
147                 if (bufsize * 2 > bufsize)  /* ..check overflow */
148                         newbuf = realloc(readbuf, bufsize * 2);
149                 if (!newbuf) {
150                         printf("skein%dsum: %s: MEM WARNING: %u bytes only readed from %llu\n",
151                                 hashbitlen, file_name, total_readed, (long long unsigned)st.st_size);
152                         break;
153                 }
154                 readbuf = newbuf;
155                 readpos += readed;
156                 bufsize *= 2;
157         }
158
159         if (total_readed < st.st_size && total_readed < bufsize) {
160                 printf("skein%dsum: %s: READ WARNING: filesize=%llu, readed=%u, %s\n",
161                         hashbitlen, file_name, (long long unsigned)st.st_size, total_readed, strerror(errno));
162         }
163
164         fclose(fp_in);
165
166         unsigned char output[hashbitlen/4];
167         Hash(hashbitlen, (unsigned char*) readbuf, total_readed, output);
168
169         free(readbuf);
170
171         printHexMsg(output,hashbitlen/4,MsgDigest);
172
173         return 1;
174 }
175
176 int HashTextMode(char file_name[], char MsgDigest[])
177 {
178         return HashWithMode(file_name, MsgDigest, 't');
179 }
180
181 int HashBinaryMode(char file_name[], char MsgDigest[])
182 {
183         return HashWithMode(file_name, MsgDigest, 'b');
184 }
185
186 int HashStringMode(char Msg[],char MsgDigest[])
187 {
188         unsigned char output[hashbitlen/4];
189         Hash(hashbitlen,(unsigned char*) Msg,sizeof(Msg),output);
190         printHexMsg(output,hashbitlen/4,MsgDigest);
191         return 1;
192 }
193
194 int isProper(char MsgDigest[])
195 {
196         if ((strlen(MsgDigest) - hashbitlen/4) != 0)
197                 return 0;
198         int index = 0;
199         char c = 0;
200         for(index = 0; index < strlen(MsgDigest);index++)
201         {
202                 c = MsgDigest[index];
203                 if(!(( c >= '0' && c <= '9' ) || ( c >= 'A' && c <= 'F')))
204                         return 0;
205         }
206
207         return 1;
208 }
209
210
211 int decomposeHashLine(char hash[], char MsgDigest_tmp[], char file_tmp[])
212 {
213         char c = 0;
214         int i = 0 , j =0;
215         int isTagFile = 0;
216         char alg[20];
217         char tmp[1000];
218         while(((c = hash[i])!=' ')&&((c = hash[i])!='_'))
219         {
220                 tmp[i] = hash[i];
221                 i++;
222         }
223         tmp[i] = 0;
224
225         sprintf(alg,"skein%d",hashbitlen);
226         if(!strcmp(alg,tmp))
227         {
228                 isTagFile = 1;
229         }
230
231         if(isTagFile == 0)
232         {
233                 strcpy(MsgDigest_tmp,tmp);
234                 i++;
235                 while((c = hash[i])!= '\n')
236                 {
237                         file_tmp[j] = hash[i];
238                         i++;
239                         j++;
240                 }
241                 file_tmp[j] = 0;
242         }
243         else if((hash[i]=='_')&&(hash[i+1]=='v'))
244         {
245                 i = i + 2;
246                 j = 0;
247                 char version[5];
248                 while((c = hash[i])!=' ')
249                 {
250                         version[j] = hash[i];
251                         i++;
252                         j++;
253                 }
254                 version[i] = 0;
255                 float vers = 0, skeinVers = 0;
256                 sscanf(version,"%f",&vers);
257                 sscanf(skeinVersion,"%f",&skeinVers);
258
259                 j = 0;
260                 i = i + 2;
261                 while((c = hash[i])!=')')
262                 {
263                         file_tmp[j] = hash[i];
264                         i++;
265                         j++;
266                 }
267                 file_tmp[j] = 0;
268
269                 i = i + 4;
270                 j = 0;
271                 while((c = hash[i])!='\n')
272                 {
273                         MsgDigest_tmp[j] = hash[i];
274                         i++;
275                         j++;
276                 }
277                 MsgDigest_tmp[j] = 0;
278
279                 if(skeinVers < vers)
280                 {//version newer than mine
281                         return (-1);
282                 }
283                 else if (skeinVers > vers)
284                 {//going to use older version than mine
285                         return (0) ;
286                 }
287                 else
288                 { //versions match
289                         return (1);
290                 }
291         }
292         return 1;
293
294 }
295
296 void print_version(void)
297 {
298         printf("skein%dsum 1.0\n", hashbitlen);
299         printf("License GPLv3+: GNU GPL version 3 or later\n");
300         printf("<http://gnu.org/licenses/gpl.html>\n");
301         printf("This is free software: you are free to change and redistribute it.\n");
302         printf("There is NO WARRANTY, to the extent permitted by law.\n");
303         exit(1);
304 }
305
306 void print_usage(void)
307 {
308         printf("Usage: skein%dsum [OPTION]... [FILE]...\n",hashbitlen);
309         printf("Print or check skein (%d-bit) checksums.\n",hashbitlen);
310         printf("With no FILE, or when FILE is -, read standard input.\n");
311         printf("\n");
312         printf("-b, --binary         read in binary mode\n");
313         printf("-c, --check          read skein sums from the FILEs and check them\n");
314         printf("--tag            create a BSD-style checksum\n");
315         printf("-t, --text           read in text mode (default)\n");
316         printf("\n");
317         printf("The following three options are useful only when verifying checksums:\n");
318         printf("--quiet          don't print OK for each successfully verified file\n");
319         printf("--status         don't output anything, status code shows success\n");
320         printf("-w, --warn           warn about improperly formatted checksum lines\n");
321         printf("\n");
322         printf("--strict         with --check, exit non-zero for any invalid input\n");
323         printf("--help     display this help and exit\n");
324         printf("--version  output version information and exit\n");
325         printf("\n");
326         printf("The sums are computed as described in version 1.3 of the Skein\n");
327         printf("specification. When checking, the input should be a former output of\n");
328         printf("this program. The default mode is to print a line with checksum, a\n");
329         printf("character indicating input mode ('*' for binary, space for text), and\n");
330         printf("name for each FILE.\n");
331         exit(1);
332 }
333
334
335
336 int main(int argc, char** argv)
337 {
338         char MsgDigest[hashbitlen/2];
339         char *list_files[MaxNmberFiles];
340         int number_files = 0;
341         int binary = -1,
342                  check = -1,
343                  quiet = -1,
344                  warn = -1,
345                  status = -1,
346                  tag = -1,
347                  hashString = -1;
348
349         int errorFound = 0;
350         int opt = 0;
351 /*****************************************************************************************
352  ************************************* GETTING DATA ***********************************
353  *****************************************************************************************/
354         while ((opt = getopt_long (argc, argv, "bctw", long_options, NULL)) != -1)
355         {
356                 switch (opt) {
357                         case 0              : hashString = 1;  break;
358                         case 'b'            : binary     = 1;  break;
359                         case 't'            : binary     = 0;  break;
360                         case 'c'            : check      = 1;  break;
361                         case 'w'            : warn       = 1;  break;
362                         case QUIET_OPTION   : quiet      = 1;  break;
363                         case STATUS_OPTION  : status     = 1;  break;
364                         case TAG_OPTION     : tag        = 1;  break;
365                         
366                         case HELP_OPTION    : print_usage();   /* ..never returns */
367                         case VERSION_OPTION : print_version(); /* ..never returns */
368
369                         default:
370                                 printf("Try `skein%dsum --help' for more information.\n",hashbitlen);
371                                 exit(1);
372                 }
373         }
374
375         for (; optind < argc; ++optind)
376         {
377                 struct stat s;
378                 if (stat(argv[optind], &s) < 0)
379                 {
380                         printf("skein%dsum: %s: no such file or directory\n", hashbitlen, argv[optind]);
381                         errorFound = 1;
382                 }
383                 else if (s.st_mode & (S_IFREG|S_IFBLK))  /* ..regular file or block device? */
384                 {
385                         if (number_files < MaxNmberFiles) {
386                                 list_files[number_files++] = argv[optind];
387                         } else {
388                                 printf("skein%dsum: %s: ignore because filelist is too long\n",
389                                         hashbitlen, argv[optind]);
390                         }
391                 }
392                 else if (s.st_mode & S_IFDIR)
393                 {
394                         printf("skein%dsum: %s: is a directory\n",hashbitlen,argv[optind]);
395                         errorFound = 1;
396                 }
397                 else
398                 {
399                         printf("skein%dsum: %s: wrong filetype 0x%Xu\n",
400                                 hashbitlen, argv[optind], s.st_mode);
401                                 errorFound = 1;
402                 }
403         }
404
405 /*****************************************************************************************
406  ************************************* PROCESSING DATA ***********************************
407  *****************************************************************************************/
408         if(argc > 1 && binary == 1)
409         {
410                 if (check == 1 || quiet == 1 || warn == 1 || status == 1)
411                 {
412                         printf("skein%dsum: the --binary and --text options are meaningless when verifying checksums\n",hashbitlen);
413                         printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
414                         exit(0);
415                 }
416                 if(number_files > 0)
417                 {
418                         int index_files = 0;
419                         while(index_files < number_files)
420                         {
421                                 if(hashString == 1)
422                                 {
423                                         printf("skein%dsum: %s: No such file or directory\n",hashbitlen,list_files[index_files]);
424                                         index_files++;
425                                         continue;
426                                 }
427                                 if(HashBinaryMode(list_files[index_files],MsgDigest)!=-1)
428                                 {
429                                         if(tag == 1)
430                                         {
431                                                 printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
432                                         }
433                                         else
434                                         {
435                                                 printf("%s ",MsgDigest);
436                                                 printf("*%s\n",list_files[index_files]);
437                                         }
438                                 }
439                                 index_files++;
440                         }
441                 }
442                 else if(errorFound != 1)
443                 { // read stdin for strings
444                         char stri[100];
445                         char longstring[1000];
446                         longstring[0] = 0;
447                         while((fgets(stri,100,stdin))!=NULL)
448                         {
449                                 strcat(longstring,stri);
450                         }
451                         HashStringMode(longstring,MsgDigest);
452                         if(tag == 1)
453                         {
454                                 printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
455                         }
456                         else
457                         {
458                                 printf("%s *-\n",MsgDigest);
459                         }
460                 }
461         }
462
463         else if (argc > 1 && binary == 0) // Text Mode
464         {
465                 if (check == 1 || quiet == 1 || warn == 1 || status == 1)
466                 {
467                         printf("skein%dsum: the --binary and --text options are meaningless when verifying checksums\n",hashbitlen);
468                         printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
469                         exit(0);
470                 }
471                 if(number_files > 0)
472                 {
473                         int index_files = 0;
474                         while(index_files < number_files)
475                         {
476                                 if(HashTextMode(list_files[index_files],MsgDigest)!=-1)
477                                 {
478                                         if(tag == 1)
479                                         {
480                                                 printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
481                                         }
482                                         else
483                                         {
484                                                 printf("%s ",MsgDigest);
485                                                 printf("%s\n",list_files[index_files]);
486                                         }
487                                 }
488                                 index_files++;
489                         }
490                 }
491                 else if(errorFound != 1)
492                 { // read stdin for strings
493                         char stri[100];
494                         char longstring[1000];
495                         longstring[0] = 0;
496                         while((fgets(stri,100,stdin))!=NULL)
497                         {
498                                 strcat(longstring,stri);
499                         }
500                         HashStringMode(longstring,MsgDigest);
501                         if(tag == 1)
502                         {
503                                 printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
504                         }
505                         else
506                         {
507                                 printf("%s -\n",MsgDigest);
508                         }
509                 }
510         }
511
512         else if (argc > 1 && binary == -1)
513         {
514                 if(check == -1)
515                 {// hashing stdin entries
516                         if(quiet == 1 || status == 1 || warn == 1)
517                         {
518                                 if(quiet == 1)
519                                         printf("skein%dsum: the --quiet option is meaningful only when verifying checksums\n",hashbitlen);
520                                 if(status ==1)
521                                         printf("skein%dsum: the --status option is meaningful only when verifying checksums\n",hashbitlen);
522                                 if(warn == 1)
523                                         printf("skein%dsum: the --warn option is meaningful only when verifying checksums\n",hashbitlen);
524
525                                 printf("Try 'skein%dsum --help' for more information.\n",hashbitlen);
526                                 exit(1);
527                         }
528                         if(number_files > 0)
529                         {// hashing files
530                                 int index_files = 0;
531                                 while(index_files < number_files)
532                                 {
533                                         if(HashTextMode(list_files[index_files],MsgDigest)!=-1)
534                                         {
535                                                 if(tag == 1)
536                                                 {
537                                                         printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
538                                                 }
539                                                 else
540                                                 {
541                                                         printf("%s ",MsgDigest);
542                                                         printf("%s\n",list_files[index_files]);
543                                                 }
544                                         }
545                                         index_files++;
546                                 }
547                         }
548                         else if(errorFound != 1)
549                         { // hasing strings read from  stdin
550                                 char stri[100];
551                                 char longstring[1000];   /* TODO!!! Fix buffer overflow!!! */
552                                 longstring[0] = 0;
553                                 while((fgets(stri,100,stdin))!=NULL)
554                                 {
555                                         strcat(longstring,stri);
556                                 }
557                                 HashStringMode(longstring,MsgDigest);
558                                 if(tag == 1)
559                                 {
560                                         printf("skein%d_v%s (-) = %s\n",hashbitlen,skeinVersion,MsgDigest);
561                                 }
562                                 else
563                                 {
564                                         printf("%s -\n",MsgDigest);
565                                 }
566                         }
567                 }
568                 else if(check == 1)
569                 {
570                         if(tag == 1)
571                         {
572                                 printf("skein%dsum: the --tag option is meaningless when verifying checksums\n",hashbitlen);
573                                 printf("Try 'skein%dsum --help' for more information\n",hashbitlen);
574                                 exit(1);
575                         }
576                         int index_files = 0;
577                         while(index_files < number_files)
578                         {
579                                 FILE *fp;
580                                 char hash[500], file_name[100], file_tmp[100], MsgDigest_tmp[hashbitlen/2];
581                                 int NoMatch = 0, NotProper = 0, Computed = 0;
582                                 strcpy(file_name,list_files[index_files]);
583                                 //show everything
584                                 int line = 0;
585                                 fp = fopen(file_name,"r");
586                                 if(fp!=NULL)
587                                 {
588                                         while(fgets(hash,500,fp)!=NULL)
589                                         {
590                                                 line ++;
591                                                 Computed++;
592                                                 unsigned int hashVersion = decomposeHashLine(hash,MsgDigest_tmp,file_tmp);
593                                                 if(hashVersion == -1)
594                                                 {
595                                                         printf("skein%d: %s is using newer version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
596                                                         printf("You should update your algorithm\n");
597                                                         continue;
598                                                 }
599                                                 else if( hashVersion == 0)
600                                                 {
601                                                         printf("skein%d: %s is using an older version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
602                                                         printf("You should use the older algorithm\n");
603                                                         continue;
604                                                 }
605                                                 else
606                                                 {
607                                                         if(!isProper(MsgDigest_tmp))
608                                                         {
609                                                                 if(status != 1 && warn == 1)
610                                                                 {
611                                                                         printf("skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_tmp,line,hashbitlen);
612                                                                 }
613                                                                 NotProper ++;
614                                                                 NoMatch ++;
615                                                                 continue;
616                                                         }
617                                                         if(file_tmp[0] == '*')
618                                                         {
619                                                                 int index_file_tmp = 0;
620                                                                 for( ; file_tmp[index_file_tmp+1]!=0 ; index_file_tmp++)
621                                                                 {
622                                                                         file_tmp[index_file_tmp] = file_tmp[index_file_tmp + 1];
623                                                                 }
624                                                                 file_tmp[index_file_tmp] = 0;
625                                                                 HashBinaryMode(file_tmp,MsgDigest);
626                                                         }
627                                                         else
628                                                         {
629                                                                 HashTextMode(file_tmp,MsgDigest);
630                                                         }
631
632                                                         if(!strcmp(MsgDigest,MsgDigest_tmp))
633                                                         {
634                                                                 if(quiet != 1)
635                                                                 {
636                                                                         printf("%s: OK\n",file_tmp);
637                                                                 }
638                                                         }
639                                                         else
640                                                         {
641                                                                 printf("%s: FAILED\n",file_tmp);
642                                                                 NoMatch ++;
643                                                         }
644                                                 }
645                                         }
646                                         if(NoMatch)
647                                         {
648                                                 printf("skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
649                                                                 hashbitlen,NoMatch,Computed);
650                                         }
651                                         if(NotProper)
652                                         {
653                                                 printf("skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
654                                         }
655                                 }
656                                 else
657                                 {
658                                         printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
659                                 }
660                                 index_files++;
661
662                         }
663
664                         if(number_files  == 0)
665                         {
666                                 char longstring[1000];
667                                 char file_name[30];
668                                 char MsgDigest_tmp[hashbitlen/2];
669                                 int Computed = 0, NotProper = 0, NoMatch = 0 , line = 0;
670                                 while((fgets(longstring,1000,stdin))!=NULL)
671                                 {
672                                         Computed++;
673                                         line ++;
674                                         decomposeHashLine(longstring,MsgDigest_tmp,file_name);
675                                         if(!isProper(MsgDigest_tmp))
676                                         {
677                                                 if(status != 1 && warn == 1)
678                                                 {
679                                                         printf("skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_name,line,hashbitlen);
680                                                 }
681                                                 NotProper ++;
682                                                 NoMatch ++;
683                                                 continue;
684                                         }
685                                         if(file_name[0] == '*')
686                                         {
687                                                 int index_file_tmp = 0;
688                                                 for( ; file_name[index_file_tmp+1]!=0 ; index_file_tmp++)
689                                                 {
690                                                         file_name[index_file_tmp] = file_name[index_file_tmp + 1];
691                                                 }
692                                                 file_name[index_file_tmp] = 0;
693                                                 HashBinaryMode(file_name,MsgDigest);
694                                         }
695                                         else
696                                         {
697                                                 HashTextMode(file_name,MsgDigest);
698                                         }
699
700                                         if(!strcmp(MsgDigest,MsgDigest_tmp))
701                                         {
702                                                 if(quiet != 1)
703                                                 {
704                                                         printf("%s: OK\n",file_name);
705                                                 }
706                                         }
707                                         else
708                                         {
709                                                 printf("%s: FAILED\n",file_name);
710                                                 NoMatch ++;
711                                         }
712                                 }
713                                 if(NoMatch)
714                                 {
715                                         printf("skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
716                                                         hashbitlen,NoMatch,Computed);
717                                 }
718                                 if(NotProper)
719                                 {
720                                         printf("skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
721                                 }
722
723                         }
724
725
726                 }
727         }
728
729         if ((errorFound != 1) && (argc == 1 || (hashString == 1 && number_files == 0)))
730         {
731                 char stri[100];
732                 char longstring[1000];
733                 longstring[0] = 0;
734                 while((fgets(stri,100,stdin))!=NULL)
735                 {
736                                 strcat(longstring,stri);
737                 }
738                 HashStringMode(longstring,MsgDigest);
739                 printf("%s -\n",MsgDigest);
740         }
741
742         return 1;
743 }