nightmaremail

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

sendmail.c (5070B)


      1 #include "sgetopt.h"
      2 #include "substdio.h"
      3 #include "subfd.h"
      4 #include "alloc.h"
      5 #include "auto_qmail.h"
      6 #include "exit.h"
      7 #include "env.h"
      8 #include "noreturn.h"
      9 #include "str.h"
     10 
     11 void _noreturn_ nomem()
     12 {
     13   substdio_putsflush(subfderr,"sendmail: fatal: out of memory\n");
     14   _exit(111);
     15 }
     16 
     17 void _noreturn_ die_usage()
     18 {
     19   substdio_putsflush(subfderr,"sendmail: usage: sendmail [ -t ] [ -fsender ] [ -Fname ] [ -bp ] [ -bs ] [ arg ... ]\n");
     20   _exit(100);
     21 }
     22 
     23 void _noreturn_ die_exptcps()
     24 {
     25   substdio_putsflush(subfderr,"sendmail: usage: sendmail [ -t ] [ -fsender ] [ -Fname ] [ -bp ] [ -bs ] [ arg ... ]\n");
     26   substdio_putsflush(subfderr,"This sendmail is qmail-sendmail from Nightmare Mail. It is not capable of running a\n");
     27   substdio_putsflush(subfderr,"TCP service by itself. Try running bin/qmail-smtpd (or bin/nmail-smtpd if you have\n");
     28   substdio_putsflush(subfderr,"UCSPI-TLS) from port 25 in inetd or in a UCSPI TCP nowait server.\n");
     29   substdio_putsflush(subfderr,"'Backgrounding' should be achieved by running your inetd or UCSPI TCP server from a\n");
     30   substdio_putsflush(subfderr,"supervisory engine like systemd, initware, runit, or S6.\n");
     31   _exit(100);
     32 }
     33 
     34 char *smtpdarg[] = { "bin/qmail-smtpd", 0 };
     35 void _noreturn_ smtpd()
     36 {
     37   if (!env_get("PROTO")) {
     38     if (!env_put("RELAYCLIENT=")) nomem();
     39     if (!env_put("DATABYTES=0")) nomem();
     40     if (!env_put("PROTO=TCP")) nomem();
     41     if (!env_put("TCPLOCALIP=127.0.0.1")) nomem();
     42     if (!env_put("TCPLOCALHOST=localhost")) nomem();
     43     if (!env_put("TCPREMOTEIP=127.0.0.1")) nomem();
     44     if (!env_put("TCPREMOTEHOST=localhost")) nomem();
     45     if (!env_put("TCPREMOTEINFO=sendmail-bs")) nomem();
     46   }
     47   execv(*smtpdarg,smtpdarg);
     48   substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-smtpd\n");
     49   _exit(111);
     50 }
     51 
     52 char *qreadarg[] = { "bin/qmail-qread", 0 };
     53 void _noreturn_ mailq()
     54 {
     55   execv(*qreadarg,qreadarg);
     56   substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-qread\n");
     57   _exit(111);
     58 }
     59 
     60 void do_sender(s)
     61 const char *s;
     62 {
     63   char *x;
     64   unsigned int n;
     65   unsigned int a;
     66   unsigned int i;
     67   
     68   env_unset("QMAILNAME");
     69   env_unset("MAILNAME");
     70   env_unset("NAME");
     71   env_unset("QMAILHOST");
     72   env_unset("MAILHOST");
     73 
     74   n = str_len(s);
     75   a = str_rchr(s, '@');
     76   if (a == n)
     77   {
     78     env_put2("QMAILUSER", s);
     79     return;
     80   }
     81   env_put2("QMAILHOST", s + a + 1);
     82 
     83   x = (char *) alloc((a + 1) * sizeof(char));
     84   if (!x) nomem();
     85   for (i = 0; i < a; i++)
     86     x[i] = s[i];
     87   x[i] = 0;
     88   env_put2("QMAILUSER", x);
     89   alloc_free(x);
     90 }
     91 
     92 int flagh;
     93 char *sender;
     94 
     95 int main(int argc, char **argv)
     96 {
     97   int opt;
     98   char **qiargv;
     99   char **arg;
    100   int i;
    101  
    102   if (chdir(auto_qmail) == -1) {
    103     substdio_putsflush(subfderr,"sendmail: fatal: unable to switch to qmail home directory\n");
    104     return 111;
    105   }
    106 
    107   flagh = 0;
    108   sender = 0;
    109   while ((opt = getopt(argc,argv,"vimte:f:p:o:B:F:EJxb:")) != opteof)
    110     switch(opt) {
    111       case 'B': break;
    112       case 't': flagh = 1; break;
    113       case 'f': sender = optarg; break;
    114       case 'F': if (!env_put2("MAILNAME",optarg)) nomem(); break;
    115       case 'p': break; /* could generate a Received line from optarg */
    116       case 'v': break; /* we don't even bother with best effort verbosity. */
    117       case 'i': break; /* qmsendmail is already transparent to leading dots. */
    118       case 'x': break; /* SVR4 stupidity */
    119       case 'm': break; /* twisted-paper-path blindness, incompetent design */
    120       case 'e': break; /* qmail has only one error mode */
    121       case 'o':
    122         switch(optarg[0]) {
    123 	  case 'd': break; /* qmail has only one delivery mode */
    124 	  case 'e': break; /* qmail only has one error mode */
    125 	  case 'i': break; /* qmail does not ignore dots */
    126 	  case 'm': break; /* qmail always sends to me too if in an EXPN. */
    127 	}
    128         break;
    129       case 'E': case 'J': /* Sony NEWS-OS */
    130         while (argv[optind][optpos]) ++optpos; /* skip optional argument */
    131         break;
    132       case 'b':
    133 	switch(optarg[0]) {
    134 	  case 'm': break;
    135 	  case 'd': die_exptcps(); /* explain TCP servers to the user */
    136 	  case 'D': die_exptcps(); /* who is probably echt confused */
    137 	  case 'p': mailq();
    138 	  case 's': smtpd();
    139 	  default: die_usage();
    140 	}
    141 	break;
    142       default:
    143 	die_usage();
    144     }
    145   argc -= optind;
    146   argv += optind;
    147 
    148   if (str_equal(optprogname,"mailq"))
    149     mailq();
    150 
    151   if (str_equal(optprogname,"newaliases")) {
    152     substdio_putsflush(subfderr,"sendmail: fatal: please use fastforward/newaliases instead\n");
    153     return 100;
    154   }
    155 
    156   qiargv = (char **) alloc((argc + 10) * sizeof(char *));
    157   if (!qiargv) nomem();
    158   /* This is arcane: qiargv is... a pointer to 10+argc pointers to char arrays.
    159    * This kind of arcana confuses dragons. We don't work in nuances. */
    160   arg = qiargv;
    161   *arg++ = "bin/qmail-inject";
    162   *arg++ = (flagh ? "-H" : "-a");
    163   if (sender) {
    164     *arg++ = "-f";
    165     *arg++ = sender;
    166     do_sender(sender);
    167   }
    168   *arg++ = "--";
    169   for (i = 0;i < argc;++i) *arg++ = argv[i];
    170   *arg = 0;
    171 
    172   execv(*qiargv,qiargv);
    173   substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-inject\n");
    174   return 111;
    175 }