Add .gitattributes
[skeinsum.git] / skein_cli.c
index 67fc0777beeb565001dda90a9bfc8c2e7785ed53..bb8235483aa91b11309102a1b26055d34436ed3e 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 2015 Jason Self <j@jxself.org>
+/* Copyright (C) 2014 2015 2019 Jason Self <j@jxself.org>
 
 This file is part of skeinsum.
 
@@ -29,7 +29,9 @@ along with skeinsum. If not, see <http://www.gnu.org/licenses/>.
 #include <glob.h>
 #include <sys/stat.h>
 #include <errno.h>
-#include "SHA3api_ref.h"
+#include "skeinapi_ref.h"
+
+#define WARN(msg, ...) fprintf(stderr, "skein%dsum: " msg, hashbitlen, ##__VA_ARGS__)
 
 #define TRYHELP_GOODBYE() do { printf("Try 'skein%dsum --help' for more information.\n", hashbitlen); exit(1); } while(0)
 
@@ -38,12 +40,11 @@ typedef long long unsigned LLU;
 extern const int hashbitlen;
 
 #define skeinVersion "1.3"
+
 const size_t input_minbufsize = 32 * 1024;
 const size_t input_maxbufsize = 32 * 1024 * 1024;
 
 
-char invalidOption = 0;
-
 enum
 {
   QUIET_OPTION = 11,
@@ -82,21 +83,21 @@ int HashFile(const char file_name[], char MsgDigest[], char mode)
        struct stat st;
        st.st_size = 0;  /* ..needed when reading from stdio */
        if (!is_stdin && stat(file_name, &st) < 0) {
-               printf("skein%dsum: %s: STAT FAILED: %s\n", hashbitlen, file_name, strerror(errno));
+               WARN("%s: cannot stat: %s\n", file_name, strerror(errno));
                return -1;
        }
 
        /* Get filesize */
        size_t fsize = st.st_size;
        if (fsize != st.st_size) {
-               printf("skein%dsum: %s: SIZE WARNING: filesize %llu is too big for reading into memory!\n",
-                       hashbitlen, file_name, (long long unsigned)st.st_size);
+               WARN("%s: SIZE WARNING: filesize %llu is too big for reading into memory!\n",
+                       file_name, (long long unsigned)st.st_size);
        }
 
        /* Open file */
        FILE *fp_in = is_stdin ? stdin : fopen(file_name, (mode == 't' ? "r" : "rb") );
        if (!fp_in) {
-               printf("skein%dsum: %s: OPEN FAILED: %s\n", hashbitlen, file_name, strerror(errno));
+               WARN("%s: cannot open: %s\n", file_name, strerror(errno));
                return -1;
        }
 
@@ -112,7 +113,7 @@ int HashFile(const char file_name[], char MsgDigest[], char mode)
        }
 
        if (!readbuf) {
-               printf("skein%dsum: %s: MEM FAILED: %s\n", hashbitlen, file_name, strerror(errno));
+               WARN("%s: MEM FAILED: error %s\n", file_name, strerror(errno));
                if (!is_stdin)
                        fclose(fp_in);
                return -1;
@@ -137,11 +138,11 @@ int HashFile(const char file_name[], char MsgDigest[], char mode)
                        newbuf = realloc(readbuf, bufsize * 2);
                if (!newbuf) {
                        if (total_readed < st.st_size) {
-                               printf("skein%dsum: %s: MEM WARNING: %llu bytes only readed from %llu\n",
-                                       hashbitlen, file_name, (LLU)total_readed, (LLU)st.st_size);
+                               WARN("%s: MEM WARNING: %llu bytes only readed from %llu\n",
+                                       file_name, (LLU)total_readed, (LLU)st.st_size);
                        } else {
-                               printf("skein%dsum: %s: MEM WARNING: %llu bytes only readed.\n",
-                                       hashbitlen, file_name, (LLU)total_readed);
+                               WARN("%s: MEM WARNING: %llu bytes only readed.\n",
+                                       file_name, (LLU)total_readed);
                        }
                        break;
                }
@@ -154,8 +155,8 @@ int HashFile(const char file_name[], char MsgDigest[], char mode)
                fclose(fp_in);
 
        if (!is_stdin && total_readed < st.st_size && total_readed < bufsize) {
-               printf("skein%dsum: %s: READ WARNING: filesize=%llu, readed=%llu, error %d, %s\n",
-                       hashbitlen, file_name, (LLU)st.st_size, (LLU)total_readed, errno, strerror(errno));
+               WARN("%s: READ WARNING: filesize=%llu, readed=%llu, error %d, %s\n",
+                       file_name, (LLU)st.st_size, (LLU)total_readed, errno, strerror(errno));
        }
 
        if (getenv("SKEIN_DUMP")) {
@@ -165,7 +166,7 @@ int HashFile(const char file_name[], char MsgDigest[], char mode)
        }
 
        unsigned char output[hashbitlen/4];
-       Hash(hashbitlen, (unsigned char*) readbuf, total_readed, output);
+       Hash(hashbitlen, (unsigned char*) readbuf, total_readed * 8, output);
 
        free(readbuf);
 
@@ -329,20 +330,22 @@ int VerifyHashesFromFile(FILE *fp, int status, int warn, int quiet)
                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");
+                       WARN("%s is using newer version of skein%d algorithm\n"
+                            "You should update your algorithm\n",
+                            file_tmp, hashbitlen);
                        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");
+                       WARN("%s is using an older version of skein%d algorithm\n"
+                            "You should use the older algorithm\n",
+                            file_tmp, hashbitlen);
                        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);
+                               WARN("%s: %d: improperly formatted skein%d checksum line\n",file_tmp,line,hashbitlen);
                        NotProper ++;
                        NoMatch ++;
                }
@@ -353,19 +356,28 @@ int VerifyHashesFromFile(FILE *fp, int status, int warn, int quiet)
        }
        if(NoMatch)
        {
-               fprintf(stderr, "skein%dsum: WARNING: %d of %d computed checksums did NOT match\n",
-                               hashbitlen,NoMatch,Computed);
+               WARN("WARNING: %d of %d computed checksums did NOT match\n",
+                       NoMatch, Computed);
        }
        if(NotProper)
        {
-               fprintf(stderr, "skein%dsum: WARNING: %d line is improperly formatted\n",hashbitlen,NotProper);
+               WARN("WARNING: %d line is improperly formatted\n", NotProper);
        }
        return (NotProper || NoMatch) ? -1 : 1;
 }
 
+void PrintStringHash(const char *s)
+{
+       unsigned char output[hashbitlen/4];
+       char digest[hashbitlen/4 + 1];
+       Hash(hashbitlen, s, strlen(s) * 8, output);
+       hash2hexstr(output, digest);
+       printf("%s -%s\n", digest, s);
+}
+
 void print_version(void)
 {
-       printf("skein%dsum 1.0\n", hashbitlen);
+       printf("skein%dsum %s\n", hashbitlen, VERSION);
        printf("License GPLv3+: GNU GPL version 3 or later\n");
        printf("<http://gnu.org/licenses/gpl.html>\n");
        printf("This is free software: you are free to change and redistribute it.\n");
@@ -375,29 +387,33 @@ void print_version(void)
 
 void print_usage(void)
 {
+
        printf("Usage: skein%dsum [OPTION]... [FILE]...\n",hashbitlen);
        printf("Print or check skein (%d-bit) checksums.\n",hashbitlen);
-       printf("With no FILE, or when FILE is -, read standard input.\n");
-       printf("\n");
-       printf("-b, --binary         read in binary mode\n");
-       printf("-c, --check          read skein sums from the FILEs and check them\n");
-       printf("--tag            create a BSD-style checksum\n");
-       printf("-t, --text           read in text mode (default)\n");
-       printf("\n");
-       printf("The following three options are useful only when verifying checksums:\n");
-       printf("--quiet          don't print OK for each successfully verified file\n");
-       printf("--status         don't output anything, status code shows success\n");
-       printf("-w, --warn           warn about improperly formatted checksum lines\n");
-       printf("\n");
-       printf("--strict         with --check, exit non-zero for any invalid input\n");
-       printf("--help     display this help and exit\n");
-       printf("--version  output version information and exit\n");
-       printf("\n");
-       printf("The sums are computed as described in version 1.3 of the Skein\n");
-       printf("specification. When checking, the input should be a former output of\n");
-       printf("this program. The default mode is to print a line with checksum, a\n");
-       printf("character indicating input mode ('*' for binary, space for text), and\n");
-       printf("name for each FILE.\n");
+       printf("With no FILE, or when FILE is -, read standard input.\n"
+              "\n"
+              "-b, --binary     read in binary mode\n"
+              "-c, --check      read skein sums from the FILEs and check them\n"
+              "--tag            create a BSD-style checksum\n"
+              "-t, --text       read in text mode (default)\n"
+              "-0               hash strings from command line\n"
+              "\n"
+              "The following three options are useful only when verifying checksums:\n"
+              "--quiet          don't print OK for each successfully verified file\n"
+              "--status         don't output anything, status code shows success\n"
+              "-w, --warn       warn about improperly formatted checksum lines\n"
+              "\n"
+              "--strict         with --check, exit non-zero for any invalid input\n"
+              "-h, --help       display this help and exit\n"
+              "-V, --version    output version information and exit\n"
+              "\n"
+              "The sums are computed as described in version %s of the Skein\n"
+              "specification. When checking, the input should be a former output of\n"
+              "this program. The default mode is to print a line with checksum, a\n"
+              "character indicating input mode ('*' for binary, space for text), and\n"
+              "name for each FILE.\n", skeinVersion);
+       printf("%s home page: %s\n", PACKAGE_NAME, PACKAGE_URL);
+        printf("Report bugs to: %s\n", PACKAGE_BUGREPORT);
        exit(1);
 }
 
@@ -409,7 +425,7 @@ int is_goodfile(const char filename[])
        struct stat s;
 
        if (stat(filename, &s) < 0) {
-               fprintf(stderr, "skein%dsum: %s: no such file or directory\n", hashbitlen, filename);
+               WARN("%s: no such file or directory\n", filename);
                return 0;
        }
 
@@ -420,14 +436,35 @@ int is_goodfile(const char filename[])
        if (S_ISFIFO(s.st_mode)) return 1;
 
        if (S_ISDIR (s.st_mode)) {
-               fprintf(stderr, "skein%dsum: %s: is a directory\n", hashbitlen, filename);
+               WARN("%s: is a directory\n", filename);
                return 0;
        }
 
-       fprintf(stderr, "skein%dsum: %s: WARNING: wrong filetype 0x%Xu\n", hashbitlen, filename, s.st_mode);
+       WARN("%s: WARNING: unknown filetype 0x%Xu\n", filename, s.st_mode);
        return 1;  /* try it as good */
 }
 
+int warn_check_opts(int quiet, int warn, int status)
+{
+       int n = 0;
+       if(quiet == 1)
+               n = WARN("the --quiet option is meaningful only when verifying checksums\n");
+       if(status ==1)
+               n = WARN("the --status option is meaningful only when verifying checksums\n");
+       if(warn == 1)
+               n = WARN("the --warn option is meaningful only when verifying checksums\n");
+       return n;
+}
+
+int warn_gen_opts(int tag, int binary)
+{
+       int n = 0;
+       if (tag == 1)
+               n = WARN("the --tag option is meaningful only when calculating file checksums\n");
+       if (binary >= 0)
+               n = WARN("the --text and --binary options are meaningful only when calculating file checksums\n");
+       return n;
+}
 
 int main(int argc, char** argv)
 {
@@ -445,10 +482,10 @@ int main(int argc, char** argv)
 /*****************************************************************************************
  ************************************* GETTING DATA ***********************************
  *****************************************************************************************/
-       while ((opt = getopt_long (argc, argv, "hVbctw", long_options, NULL)) != -1)
+       while ((opt = getopt_long (argc, argv, "hVbctw0", long_options, NULL)) != -1)
        {
                switch (opt) {
-                       case 0              : hashString = 1;  break;
+                       case '0'            : hashString = 1;  break;
                        case 'b'            : binary     = 1;  break;
                        case 't'            : binary     = 0;  break;
                        case 'c'            : check      = 1;  break;
@@ -470,18 +507,25 @@ int main(int argc, char** argv)
  ************************************* PROCESSING DATA ***********************************
  *****************************************************************************************/
 
-       if (check < 0)   /* READ FILES, GENERATE CHECKSUMS AND PRINT TO STDOUT.. */
+       if (hashString > 0)
        {
-               if (quiet == 1 || warn == 1 || status == 1)
-               {
-                       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);
+               if (warn_check_opts(quiet, warn, status) + warn_gen_opts(tag, binary))
+                       TRYHELP_GOODBYE();
+
+               int n = first_file;
+               if (n >= argc) {
+                       WARN("command line should contain strings for hashing\n");
                        TRYHELP_GOODBYE();
                }
+               while (n < argc)
+                       PrintStringHash(argv[n++]);
+               return 0;
+       }
+
+       if (check < 0)   /* READ FILES, GENERATE CHECKSUMS AND PRINT TO STDOUT.. */
+       {
+               if (warn_check_opts(quiet, warn, status))
+                       TRYHELP_GOODBYE();
 
                char mode = binary > 0 ? 'b' : 't';
 
@@ -495,7 +539,7 @@ int main(int argc, char** argv)
                        }
 
                        if (binary > 0 && hashString == 1) {
-                               printf("skein%dsum: %s: No such file or directory\n", hashbitlen, filename);
+                               WARN("%s: No such file or directory\n", filename);
                                continue;
                        }
 
@@ -512,14 +556,8 @@ int main(int argc, char** argv)
 
        if (check == 1)   /* READ LISTFILES, GENERATE HASHES, COMPARE WITH STORED, PRINT RESULT */
        {
-               if (tag == 1 || binary >= 0)
-               {
-                       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);
+               if (warn_gen_opts(tag, binary))
                        TRYHELP_GOODBYE();
-               }
 
                int file_index;
                for (file_index = first_file; file_index < argc; file_index++)
@@ -533,7 +571,7 @@ int main(int argc, char** argv)
                        FILE *fp = (strcmp(filename, "-") == 0) ? stdin : fopen(filename, "r");
                        if (!fp) {
                                errorFound++;
-                               printf("skein%dsum: %s: error %d, %s\n", hashbitlen, filename, errno, strerror(errno));
+                               WARN("%s: %s\n", filename, strerror(errno));
                                continue;
                        }
                        if (VerifyHashesFromFile(fp, status, warn, quiet) < 0)