sendmail: Replace shell script by C implementation
authorStefan Huber <shuber@sthu.org>
Wed, 6 Jan 2021 20:47:58 +0000 (21:47 +0100)
committerStefan Huber <shuber@sthu.org>
Wed, 6 Jan 2021 20:47:58 +0000 (21:47 +0100)
The C implementation allows sendmail to have the suid flag set, which
might be required for some use cases.

.gitignore
Makefile
sendmail [deleted file]
sendmail.c [new file with mode: 0644]

index e5a8566079777d883a598c13b0984835c20cdfc4..a2fcdd598712a9e7b5a20349fec32af45d3e493c 100644 (file)
@@ -2,3 +2,4 @@ smailq.1
 debian/smailq/
 debian/tmp/
 debian/.debhelper/
+sendmail
index aa72315f3be33cb2397198755b945947561d340d..7c3b37bfdabda427e8c01663c41ca0ad9832975e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,6 @@
 PREFIX ?= /usr
 BIN_SUFFIX ?=
+CFLAGS = -std=c99 -pedantic -Wall -Wextra
 
 # Where the script binary should go
 BINPATH = $(DESTDIR)$(PREFIX)/bin
@@ -9,7 +10,7 @@ SHAREDIR = $(DESTDIR)$(PREFIX)/share/smailq
 CONFFILE = $(SHAREDIR)/smailq.conf.sample
 ######################################################################
 
-all: manpage
+all: sendmail manpage
 
 install: all
        mkdir -p $(BINPATH) $(SBINPATH) $(MANPATH) $(SHAREDIR)
diff --git a/sendmail b/sendmail
deleted file mode 100755 (executable)
index 8a9df55..0000000
--- a/sendmail
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-
-# Copyright (c) 2013 Stefan Huber <shuber@sthu.org>
-
-set -e
-
-CMD="$(dirname $0)/smailq"
-options=
-list="0"
-
-usage() {
-    cat << EOF
-A wrapper script for smailq that behaves like sendmail. 
-
-USAGE:
-  $0 [OPTIONS] [recipient ...]
-  $0 --help  
-
-It simply calls '$CMD --send -- [OPTIONS] [recipient ...]'. In
-particular, it passes all options as MSA options to smailq.
-EOF
-}
-
-
-options=()
-while [ $# -gt "0" ]; do
-    if [ "$1" == "-bp" ]; then
-        list="1"
-    else
-        options+=("$1")
-    fi
-    shift
-done
-
-if [ "$list" = "1" ]; then
-    smailq --list
-else
-    smailq --send -- "${options[@]}"
-fi
-
diff --git a/sendmail.c b/sendmail.c
new file mode 100644 (file)
index 0000000..8e2aa4f
--- /dev/null
@@ -0,0 +1,63 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static void usage(char* arg0) {
+    puts("A wrapper script for smailq that mimics sendmail.\n"
+         "USAGE:\n");
+    printf("  %s [OPTIONS] [recipient ...]\n", arg0);
+    printf("  %s -bp\n", arg0);
+    puts("\n"
+         "OPTIONS:\n"
+         "  -bp\n"
+         "     Calls `smailq --list`\n"
+         "\n"
+         "  -h\n"
+         "     Prints this help text\n"
+         "\n"
+         "  [OPTIONS] [recipient ...]\n"
+         "     Calls `smailq --send -- [OPTIONS] [recipient ...]`.\n"
+         "     It passes all options as MSA options to smailq.\n");
+}
+
+int main(int argc, char* argv[]) {
+    if (argc == 1) {
+        fputs("No arguments given.\n", stderr);
+        usage(argv[0]);
+        return EINVAL;
+    }
+
+    if (strcmp(argv[1], "-h") == 0) {
+        usage(argv[0]);
+        return EXIT_SUCCESS;
+    }
+
+    if (strcmp(argv[1], "-bp") == 0) {
+        execlp("smailq", "smailq", "list", NULL);
+        perror("Error calling smailq --list");
+        return EXIT_FAILURE;
+    }
+
+    /* We have to add two more arguments: -- --send */
+    char** newargv = malloc((argc+2)*sizeof(char*));
+    if (newargv == NULL) {
+        perror(NULL);
+        return EXIT_FAILURE;
+    }
+
+    /* Fill in the arguments for smailq. Note that argv[argc] is NULL and
+     * newargv must be termined by a NULL pointer for execvp(). */
+    newargv[0] = "smailq";
+    newargv[1] = "--send";
+    newargv[2] = "--";
+    for (int i=1; i <= argc; ++i)
+        newargv[2+i] = argv[i];
+
+    execvp("smailq", newargv);
+    perror("Error calling smailq --list");
+    free(newargv);
+    return EXIT_FAILURE;
+}