skein_cli main routine simplified.
[skeinsum.git] / skein_cli.c
index 0ea815bbda0f965110f3c8cfee10e4d38779a67b..f2bc2e27caeec23d8e638d239ae83161d20e8c86 100644 (file)
@@ -35,7 +35,6 @@ along with skeinsum. If not, see <http://www.gnu.org/licenses/>.
 
 extern const int hashbitlen;
 
-#define MaxNmberFiles 10
 #define skeinVersion "1.3"
 const size_t input_minbufsize = 32 * 1024;
 const size_t input_maxbufsize = 32 * 1024 * 1024;
@@ -92,7 +91,7 @@ void printHexMsg(unsigned char *ptr, int size, char result[])
        result[i] = 0;
 }
 
-int HashWithMode(char file_name[], char MsgDigest[], char mode)
+int HashWithMode(const char file_name[], char MsgDigest[], char mode)
 {
        /* Try to get file info */
        struct stat st;
@@ -175,38 +174,111 @@ int HashWithMode(char file_name[], char MsgDigest[], char mode)
        return 1;
 }
 
-int HashTextMode(char file_name[], char MsgDigest[])
+int PrintHash(const char filename[], int tag, char mode)
 {
-       return HashWithMode(file_name, MsgDigest, 't');
-}
-
-int HashBinaryMode(char file_name[], char MsgDigest[])
-{
-       return HashWithMode(file_name, MsgDigest, 'b');
+       char MsgDigest[hashbitlen/2];
+       if (HashWithMode(filename, MsgDigest, mode) < 0)
+               return -1;
+       if (tag == 1) {
+               printf("skein%d_v%s (%s) = %s\n", hashbitlen, skeinVersion, filename, MsgDigest);
+       } else {
+               printf("%s %s%s\n", MsgDigest, (mode == 'b' ? "*" : ""), filename);
+       }
+       return 1;
 }
 
-void HashStringMode(char Msg[],char MsgDigest[])
+void HashStringMode(const char Msg[], char MsgDigest[])
 {
        unsigned char output[hashbitlen/4];
-       Hash(hashbitlen,(unsigned char*) Msg,sizeof(Msg),output);
+       Hash(hashbitlen, (unsigned char*) Msg, strlen(Msg), output);
        printHexMsg(output,hashbitlen/4,MsgDigest);
 }
 
-void HashStdin(char MsgDigest[], int tag)
+void HashStdin(int tag)
 {
-       char stri[100];
+       char MsgDigest[hashbitlen/2];
+       char stri[100];             /* TODO!!! REWRITE THIS HARDCORE!!! */
        char longstring[1000];
        longstring[0] = 0;
        while(fgets(stri,100,stdin))
                strcat(longstring, stri);
        HashStringMode(longstring, MsgDigest);
-       if (tag) {
+       if (tag == 1) {
                printf("skein%d_v%s (-) = %s\n", hashbitlen, skeinVersion, MsgDigest);
        } else {
                printf("%s *-\n", MsgDigest);
        }
 }
 
+int HashMatch(const char StoredDigest[], const char *filename, int quiet)
+{
+       char mode = 't';
+       if (filename[0] == '*') {
+               filename++;
+               mode = 'b';
+       }
+       
+       char MsgDigest[hashbitlen/2];
+       if (HashWithMode(filename, MsgDigest, mode) < 0)
+               return 0;
+
+       if (strcmp(MsgDigest, StoredDigest)) {
+               printf("%s: FAILED\n", filename);
+               return 0;
+       }
+       if (quiet > 0)
+               printf("%s: OK\n", filename);
+       return 1;
+}
+
+int VerifyHashesFromFile(FILE *fp, int status, int warn, int quiet)
+{
+       char hash[500], MsgDigest_tmp[hashbitlen/2];
+       int NoMatch = 0, NotProper = 0, Computed = 0;
+       int line = 0;
+
+       while (fgets(hash, sizeof(hash)-1, fp))
+       {
+               char file_tmp[PATH_MAX];
+               line ++;
+               Computed++;
+               unsigned int hashVersion = decomposeHashLine(hash,MsgDigest_tmp,file_tmp);
+               if (hashVersion == -1)
+               {
+                       fprintf(stderr, "skein%d: %s is using newer version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
+                       fprintf(stderr, "You should update your algorithm\n");
+                       continue;
+               }
+               else if (hashVersion == 0)
+               {
+                       fprintf(stderr, "skein%d: %s is using an older version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
+                       fprintf(stderr, "You should use the older algorithm\n");
+                       continue;
+               }
+               else if (!isProper(MsgDigest_tmp))
+               {
+                       if(status != 1 && warn == 1)
+                               fprintf(stderr, "skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_tmp,line,hashbitlen);
+                       NotProper ++;
+                       NoMatch ++;
+               }
+               else if (!HashMatch(MsgDigest_tmp, file_tmp, quiet))
+               {
+                       NoMatch++;
+               }
+       }
+       if(NoMatch)
+       {
+               fprintf(stderr, "skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
+                               hashbitlen,NoMatch,Computed);
+       }
+       if(NotProper)
+       {
+               fprintf(stderr, "skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
+       }
+       return (NotProper || NoMatch) ? -1 : 1;
+}
+
 int isProper(char MsgDigest[])
 {
        if ((strlen(MsgDigest) - hashbitlen/4) != 0)
@@ -347,13 +419,35 @@ void print_usage(void)
        exit(1);
 }
 
+int is_goodfile(const char filename[], int verbose)
+{
+       if (!strcmp(filename, "-"))
+               return 1;
+
+       struct stat s;
+
+       if (stat(filename, &s) < 0) {
+               if (verbose) fprintf(stderr, "skein%dsum: %s: no such file or directory\n", hashbitlen, filename);
+               return 0;
+       }
+
+       if (s.st_mode & (S_IFREG|S_IFBLK))  /* ..regular file or block device? */
+               return 1;
+
+       if (s.st_mode & S_IFDIR) {
+               if (verbose) fprintf(stderr, "skein%dsum: %s: is a directory\n", hashbitlen, filename);
+               return 0;
+       }
+
+       fprintf(stderr, "skein%dsum: %s: wrong filetype 0x%Xu\n", hashbitlen, filename, s.st_mode);
+       return 0;
+}
 
 
 int main(int argc, char** argv)
 {
-       char MsgDigest[hashbitlen/2];
-       char *list_files[MaxNmberFiles];
        int number_files = 0;
+       int first_file = argc;
        int binary = -1,
                 check = -1,
                 quiet = -1,
@@ -386,312 +480,88 @@ int main(int argc, char** argv)
                }
        }
 
-       for (; optind < argc; ++optind)
-       {
-               struct stat s;
-               if (stat(argv[optind], &s) < 0)
-               {
-                       printf("skein%dsum: %s: no such file or directory\n", hashbitlen, argv[optind]);
-                       errorFound = 1;
-               }
-               else if (s.st_mode & (S_IFREG|S_IFBLK))  /* ..regular file or block device? */
-               {
-                       if (number_files < MaxNmberFiles) {
-                               list_files[number_files++] = argv[optind];
-                       } else {
-                               printf("skein%dsum: %s: ignore because filelist is too long\n",
-                                       hashbitlen, argv[optind]);
-                       }
-               }
-               else if (s.st_mode & S_IFDIR)
-               {
-                       printf("skein%dsum: %s: is a directory\n",hashbitlen,argv[optind]);
-                       errorFound = 1;
-               }
-               else
-               {
-                       printf("skein%dsum: %s: wrong filetype 0x%Xu\n",
-                               hashbitlen, argv[optind], s.st_mode);
-                               errorFound = 1;
-               }
-       }
+       first_file = optind;
 
 /*****************************************************************************************
  ************************************* PROCESSING DATA ***********************************
  *****************************************************************************************/
-       if(argc > 1 && binary == 1)
+
+       if (check < 0)   /* READ FILES, GENERATE CHECKSUMS AND PRINT TO STDOUT.. */
        {
-               if (check == 1 || quiet == 1 || warn == 1 || status == 1)
+               if (quiet == 1 || warn == 1 || status == 1)
                {
-                       printf("skein%dsum: the --binary and --text options are meaningless when verifying checksums\n",hashbitlen);
+                       if(quiet == 1)
+                               fprintf(stderr, "skein%dsum: the --quiet option is meaningful only when verifying checksums\n", hashbitlen);
+                       if(status ==1)
+                               fprintf(stderr, "skein%dsum: the --status option is meaningful only when verifying checksums\n", hashbitlen);
+                       if(warn == 1)
+                               fprintf(stderr, "skein%dsum: the --warn option is meaningful only when verifying checksums\n", hashbitlen);
                        TRYHELP_GOODBYE();
                }
-               if(number_files > 0)
+
+               int file_index;
+               for (file_index = first_file; file_index < argc; file_index++)
                {
-                       int index_files = 0;
-                       while(index_files < number_files)
-                       {
-                               if(hashString == 1)
-                               {
-                                       printf("skein%dsum: %s: No such file or directory\n",hashbitlen,list_files[index_files]);
-                                       index_files++;
-                                       continue;
-                               }
-                               if(HashBinaryMode(list_files[index_files],MsgDigest)!=-1)
-                               {
-                                       if(tag == 1)
-                                       {
-                                               printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
-                                       }
-                                       else
-                                       {
-                                               printf("%s ",MsgDigest);
-                                               printf("*%s\n",list_files[index_files]);
-                                       }
-                               }
-                               index_files++;
+                       const char *filename = argv[file_index];
+                       if (!is_goodfile(filename, 1)) {
+                               errorFound++;
+                               continue;
                        }
+                       number_files++;
+
+                       if (binary > 0 && hashString == 1) {
+                               printf("skein%dsum: %s: No such file or directory\n", hashbitlen, filename);
+                               continue;
+                       }
+
+                       char mode = binary > 0 ? 'b' : 't';
+                       if (PrintHash(filename, tag, mode) < 0)
+                               errorFound++;
                }
-               else if(errorFound != 1)
-               {
-                       HashStdin(MsgDigest, tag);
-               }
+
+               if (!number_files && !errorFound)
+                       HashStdin(tag);
+
+               return (errorFound ? 1 : 0);
        }
 
-       else if (argc > 1 && binary == 0) // Text Mode
+       if (check == 1)   /* READ LISTFILES, GENERATE HASHES, COMPARE WITH STORED, PRINT RESULT */
        {
-               if (check == 1 || quiet == 1 || warn == 1 || status == 1)
+               if (tag == 1 || binary >= 0)
                {
-                       printf("skein%dsum: the --binary and --text options are meaningless when verifying checksums\n",hashbitlen);
+                       if (tag == 1)
+                               fprintf(stderr, "skein%dsum: the --tag option is meaningless when verifying checksums\n", hashbitlen);
+                       if (binary >= 0)
+                               fprintf(stderr, "skein%dsum: the --text and --binary options are meaningless when verifying checksums\n", hashbitlen);
                        TRYHELP_GOODBYE();
                }
-               if(number_files > 0)
-               {
-                       int index_files = 0;
-                       while(index_files < number_files)
-                       {
-                               if(HashTextMode(list_files[index_files],MsgDigest)!=-1)
-                               {
-                                       if(tag == 1)
-                                       {
-                                               printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
-                                       }
-                                       else
-                                       {
-                                               printf("%s ",MsgDigest);
-                                               printf("%s\n",list_files[index_files]);
-                                       }
-                               }
-                               index_files++;
-                       }
-               }
-               else if(errorFound != 1)
-               {
-                       HashStdin(MsgDigest, tag);
-               }
-       }
 
-       else if (argc > 1 && binary == -1)
-       {
-               if(check == -1)
-               {// hashing stdin entries
-                       if(quiet == 1 || status == 1 || warn == 1)
-                       {
-                               if(quiet == 1)
-                                       printf("skein%dsum: the --quiet option is meaningful only when verifying checksums\n",hashbitlen);
-                               if(status ==1)
-                                       printf("skein%dsum: the --status option is meaningful only when verifying checksums\n",hashbitlen);
-                               if(warn == 1)
-                                       printf("skein%dsum: the --warn option is meaningful only when verifying checksums\n",hashbitlen);
-                               TRYHELP_GOODBYE();
-                       }
-                       if(number_files > 0)
-                       {// hashing files
-                               int index_files = 0;
-                               while(index_files < number_files)
-                               {
-                                       if(HashTextMode(list_files[index_files],MsgDigest)!=-1)
-                                       {
-                                               if(tag == 1)
-                                               {
-                                                       printf("skein%d_v%s (%s) = %s\n",hashbitlen,skeinVersion,list_files[index_files],MsgDigest);
-                                               }
-                                               else
-                                               {
-                                                       printf("%s ",MsgDigest);
-                                                       printf("%s\n",list_files[index_files]);
-                                               }
-                                       }
-                                       index_files++;
-                               }
-                       }
-                       else if(errorFound != 1)
-                       {
-                               HashStdin(MsgDigest, tag);
-                       }
-               }
-               else if(check == 1)
+               int file_index;
+               for (file_index = first_file; file_index < argc; file_index++)
                {
-                       if(tag == 1)
-                       {
-                               printf("skein%dsum: the --tag option is meaningless when verifying checksums\n",hashbitlen);
-                               TRYHELP_GOODBYE();
-                       }
-                       int index_files = 0;
-                       while(index_files < number_files)
-                       {
-                               FILE *fp;
-                               char hash[500], file_name[100], file_tmp[100], MsgDigest_tmp[hashbitlen/2];
-                               int NoMatch = 0, NotProper = 0, Computed = 0;
-                               strcpy(file_name,list_files[index_files]);
-                               //show everything
-                               int line = 0;
-                               fp = fopen(file_name,"r");
-                               if(fp!=NULL)
-                               {
-                                       while(fgets(hash,500,fp)!=NULL)
-                                       {
-                                               line ++;
-                                               Computed++;
-                                               unsigned int hashVersion = decomposeHashLine(hash,MsgDigest_tmp,file_tmp);
-                                               if(hashVersion == -1)
-                                               {
-                                                       printf("skein%d: %s is using newer version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
-                                                       printf("You should update your algorithm\n");
-                                                       continue;
-                                               }
-                                               else if( hashVersion == 0)
-                                               {
-                                                       printf("skein%d: %s is using an older version of skein%d algorithm\n",hashbitlen,file_tmp,hashbitlen);
-                                                       printf("You should use the older algorithm\n");
-                                                       continue;
-                                               }
-                                               else
-                                               {
-                                                       if(!isProper(MsgDigest_tmp))
-                                                       {
-                                                               if(status != 1 && warn == 1)
-                                                               {
-                                                                       printf("skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_tmp,line,hashbitlen);
-                                                               }
-                                                               NotProper ++;
-                                                               NoMatch ++;
-                                                               continue;
-                                                       }
-                                                       if(file_tmp[0] == '*')
-                                                       {
-                                                               int index_file_tmp = 0;
-                                                               for( ; file_tmp[index_file_tmp+1]!=0 ; index_file_tmp++)
-                                                               {
-                                                                       file_tmp[index_file_tmp] = file_tmp[index_file_tmp + 1];
-                                                               }
-                                                               file_tmp[index_file_tmp] = 0;
-                                                               HashBinaryMode(file_tmp,MsgDigest);
-                                                       }
-                                                       else
-                                                       {
-                                                               HashTextMode(file_tmp,MsgDigest);
-                                                       }
-
-                                                       if(!strcmp(MsgDigest,MsgDigest_tmp))
-                                                       {
-                                                               if(quiet != 1)
-                                                               {
-                                                                       printf("%s: OK\n",file_tmp);
-                                                               }
-                                                       }
-                                                       else
-                                                       {
-                                                               printf("%s: FAILED\n",file_tmp);
-                                                               NoMatch ++;
-                                                       }
-                                               }
-                                       }
-                                       if(NoMatch)
-                                       {
-                                               printf("skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
-                                                               hashbitlen,NoMatch,Computed);
-                                       }
-                                       if(NotProper)
-                                       {
-                                               printf("skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
-                                       }
-                               }
-                               else
-                               {
-                                       printf("skein%dsum: %s: No such file or directory\n",hashbitlen,file_name);
-                               }
-                               index_files++;
-
+                       const char *filename = argv[file_index];
+                       if (!is_goodfile(filename, 1)) {
+                               errorFound++;
+                               continue;
                        }
+                       number_files++;
 
-                       if(number_files  == 0)
-                       {
-                               char longstring[1000];
-                               char file_name[30];
-                               char MsgDigest_tmp[hashbitlen/2];
-                               int Computed = 0, NotProper = 0, NoMatch = 0 , line = 0;
-                               while((fgets(longstring,1000,stdin))!=NULL)
-                               {
-                                       Computed++;
-                                       line ++;
-                                       decomposeHashLine(longstring,MsgDigest_tmp,file_name);
-                                       if(!isProper(MsgDigest_tmp))
-                                       {
-                                               if(status != 1 && warn == 1)
-                                               {
-                                                       printf("skein%dsum: %s: %d: improperly formatted skein%d checksum line\n",hashbitlen,file_name,line,hashbitlen);
-                                               }
-                                               NotProper ++;
-                                               NoMatch ++;
-                                               continue;
-                                       }
-                                       if(file_name[0] == '*')
-                                       {
-                                               int index_file_tmp = 0;
-                                               for( ; file_name[index_file_tmp+1]!=0 ; index_file_tmp++)
-                                               {
-                                                       file_name[index_file_tmp] = file_name[index_file_tmp + 1];
-                                               }
-                                               file_name[index_file_tmp] = 0;
-                                               HashBinaryMode(file_name,MsgDigest);
-                                       }
-                                       else
-                                       {
-                                               HashTextMode(file_name,MsgDigest);
-                                       }
-
-                                       if(!strcmp(MsgDigest,MsgDigest_tmp))
-                                       {
-                                               if(quiet != 1)
-                                               {
-                                                       printf("%s: OK\n",file_name);
-                                               }
-                                       }
-                                       else
-                                       {
-                                               printf("%s: FAILED\n",file_name);
-                                               NoMatch ++;
-                                       }
-                               }
-                               if(NoMatch)
-                               {
-                                       printf("skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
-                                                       hashbitlen,NoMatch,Computed);
-                               }
-                               if(NotProper)
-                               {
-                                       printf("skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
-                               }
-
+                       FILE *fp = fopen(filename, "r");
+                       if (!fp) {
+                               printf("skein%dsum: %s: error %d, %s\n", hashbitlen, filename, errno, strerror(errno));
+                               continue;
                        }
+                       if (VerifyHashesFromFile(fp, status, warn, quiet) < 0)
+                               errorFound++;
+                       fclose(fp);
+               }
 
+               if (!number_files && !errorFound)
+                       if (VerifyHashesFromFile(stdin, status, warn, quiet) < 0)
+                               errorFound++;
 
-               }
+               return (errorFound ? 1 : 0);
        }
 
-       if (!errorFound && (argc == 1 || (hashString == 1 && !number_files)))
-               HashStdin(MsgDigest, 0);
-
        return 1;
 }