1

I am trying to write a program using execlp() to save the output of an md5sum of a string to the standard output. Basically, to simulate this:

echo "Hello!" | md5sum

Which gets this output:

31ebdfce8b77ac49d7f5506dd1495830  -

Here is what I tried first to figure this out:

char string[] = "Hello!";
execlp("md5sum", "md5sum", string, NULL); 

Although, using execlp() in this way expects the argument to be a file, not a string. So then I tried this:

char string[] = "Hello!";
execlp("echo", "echo", string, "md5sum", NULL);

Although, this generates an output of Hello! md5sum. It recognizes the "md5sum" as a string, not the system call.

What can I do to make echo and md5sum cooperate together? Or what can I do to make md5sum work on a string, not a file? Maybe should I be using a different function than execlp() ?

  • 1
    You need pipe, fork and execlp to do the job. – Jonathan Leffler Oct 15 '16 at 00:43
  • md5sum doesn't take a string, it takes a file. – Schwern Oct 15 '16 at 00:43
  • `md5sum` can read from `stdin` obviously. Go with @JonathanLeffler suggestion – alvits Oct 15 '16 at 00:49
  • In the shell, `stdin` of `md5sum` is `stdout` of `echo`. You need to imitate that as the first comment suggests. – Iharob Al Asimi Oct 15 '16 at 00:50
  • It is a cool exercise in unix programming to fork and exec a process, feeding it a string through one pipe and collecting the output through another one, and every unix programmer should write that code once because it will help you understand some important concepts. But for normal usage, using a library function is faster and usually easier. [Wikipedia](https://en.m.wikipedia.org/wiki/Comparison_of_cryptography_libraries) might help you find one. (For crypto, use only reputable libraries, and make sure you unit test; comparing your output with a command-line utility is also good. – rici Oct 15 '16 at 01:56

1 Answers1

1

Before I answer your question, some concerns.

And MD5 is long, long, long since broken. It's fairly trivial to create a file with a given MD5 sum. SHA1 is on its way out. Use SHA-256 or better. Doesn't matter if your application isn't about security, you and I aren't qualified to make decisions about attack surfaces, don't take the risk.

Have you considered doing the checksum in C? It will be faster, more portable, and more reliable. There's any number of checksum libraries. Gnome Lib provides checksums, and so much more.

#include <stdio.h>
#include <glib.h>

int main() {
    char string[] = "Hello!";

    printf("checksum for %s is %s\n",
           string,
           g_compute_checksum_for_string(G_CHECKSUM_SHA256, string, -1)
    );
}

Ok, on to the question.


First problem is md5sum doesn't take a string, it takes a file. This has nothing to do with execlp, it's how the md5sum program works. You can make md5sum read from stdin, but that involves pipes and is more and I want to take on. Did I mention to use a library?

This leads to your second problem: error checking. I don't see any. Any error checking for an exec goes immediately after the exec; if it succeeded then the calling program will immediately exit.

Then problem is execlp is probably overkill unless you're changing the name of the program being run. Use execvp. I prefer it because it keeps all the program's arguments together in a nice list that can be used for error checking later.

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main() {
    char *args[] = { "md5um", "Hello!", NULL };

    int exit_status = execvp(args[0], args);

    fprintf(stderr, "executing %s ", args[0]);
    for( int i = 1; args[i] != NULL; i++ ) {
        fprintf(stderr, "%s ", args[i]);
    }
    fprintf(stderr, "exited with %d: %s\n", exit_status, strerror(errno));
}
Schwern
  • 153,029
  • 25
  • 195
  • 336