qsmhook.c
changeset 0 068428edee47
equal deleted inserted replaced
-1:000000000000 0:068428edee47
       
     1 #include "fd.h"
       
     2 #include "stralloc.h"
       
     3 #include "readwrite.h"
       
     4 #include "sgetopt.h"
       
     5 #include "wait.h"
       
     6 #include "env.h"
       
     7 #include "byte.h"
       
     8 #include "str.h"
       
     9 #include "alloc.h"
       
    10 #include "exit.h"
       
    11 #include "fork.h"
       
    12 #include "case.h"
       
    13 #include "subfd.h"
       
    14 #include "error.h"
       
    15 #include "substdio.h"
       
    16 #include "sig.h"
       
    17 
       
    18 void die(e,s) int e; char *s; { substdio_putsflush(subfderr,s); _exit(e); }
       
    19 void die_usage() { die(100,"qsmhook: fatal: incorrect usage\n"); }
       
    20 void die_temp() { die(111,"qsmhook: fatal: temporary problem\n"); }
       
    21 void die_read() { die(111,"qsmhook: fatal: unable to read message\n"); }
       
    22 void die_badcmd() { die(100,"qsmhook: fatal: command not found\n"); }
       
    23 
       
    24 int flagrpline = 0; char *rpline;
       
    25 int flagufline = 1; char *ufline;
       
    26 int flagdtline = 0; char *dtline;
       
    27 char *host;
       
    28 char *sender;
       
    29 char *recip;
       
    30 
       
    31 stralloc newarg = {0};
       
    32 
       
    33 substdio ssout;
       
    34 char outbuf[SUBSTDIO_OUTSIZE];
       
    35 substdio ssin;
       
    36 char inbuf[SUBSTDIO_INSIZE];
       
    37 
       
    38 void main(argc,argv)
       
    39 int argc;
       
    40 char **argv;
       
    41 {
       
    42  int pid;
       
    43  int wstat;
       
    44  int pi[2];
       
    45  int opt;
       
    46  char **arg;
       
    47  char *x;
       
    48  int i;
       
    49  int flagesc;
       
    50 
       
    51  sig_pipeignore();
       
    52 
       
    53  if (!(dtline = env_get("DTLINE"))) die_usage();
       
    54  if (!(rpline = env_get("RPLINE"))) die_usage();
       
    55  if (!(ufline = env_get("UFLINE"))) die_usage();
       
    56  if (!(recip = env_get("LOCAL"))) die_usage();
       
    57  if (!(host = env_get("HOST"))) die_usage();
       
    58  if (!(sender = env_get("SENDER"))) die_usage();
       
    59 
       
    60  while ((opt = getopt(argc,argv,"DFlMmnPsx:")) != opteof)
       
    61    switch(opt)
       
    62     {
       
    63      case 'D': case 'F': case 'M': break; /* be serious */
       
    64      case 'l': flagdtline = 1; break; /* also return-receipt-to? blech */
       
    65      case 'm': break; /* we only handle one recipient anyway */
       
    66      case 'n': flagufline = 0; break;
       
    67      case 's': break; /* could call quote() otherwise, i suppose... */
       
    68      case 'P': flagrpline = 1; break;
       
    69      case 'x':
       
    70        if (case_starts(recip,optarg))
       
    71 	 recip += str_len(optarg);
       
    72        break;
       
    73      default:
       
    74        _exit(100);
       
    75     }
       
    76  argc -= optind;
       
    77  argv += optind;
       
    78 
       
    79  if (!*argv) die_usage();
       
    80 
       
    81  for (arg = argv;x = *arg;++arg)
       
    82   {
       
    83    if (!stralloc_copys(&newarg,"")) die_temp();
       
    84    flagesc = 0;
       
    85    for (i = 0;x[i];++i)
       
    86      if (flagesc)
       
    87       {
       
    88        switch(x[i])
       
    89 	{
       
    90 	 case '%': if (!stralloc_cats(&newarg,"%")) die_temp(); break;
       
    91 	 case 'g': if (!stralloc_cats(&newarg,sender)) die_temp(); break;
       
    92 	 case 'h': if (!stralloc_cats(&newarg,host)) die_temp(); break;
       
    93 	 case 'u': if (!stralloc_cats(&newarg,recip)) die_temp(); break;
       
    94 	}
       
    95        flagesc = 0;
       
    96       }
       
    97      else
       
    98        if (x[i] == '%')
       
    99 	 flagesc = 1;
       
   100        else
       
   101 	 if (!stralloc_append(&newarg,&x[i])) die_temp();
       
   102    if (!stralloc_0(&newarg)) die_temp();
       
   103    i = str_len(newarg.s) + 1;
       
   104    if (!(x = alloc(i))) die_temp();
       
   105    byte_copy(x,i,newarg.s);
       
   106    *arg = x;
       
   107   }
       
   108 
       
   109  if (pipe(pi) == -1) die_temp();
       
   110 
       
   111  switch(pid = fork())
       
   112   {
       
   113    case -1:
       
   114      die_temp();
       
   115    case 0:
       
   116      close(pi[1]);
       
   117      if (fd_move(0,pi[0]) == -1) die_temp();
       
   118      sig_pipedefault();
       
   119      execvp(*argv,argv);
       
   120      if (error_temp(errno)) die_temp();
       
   121      die_badcmd();
       
   122   }
       
   123  close(pi[0]);
       
   124 
       
   125  substdio_fdbuf(&ssout,write,pi[1],outbuf,sizeof(outbuf));
       
   126  substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
       
   127  if (flagufline) substdio_bputs(&ssout,ufline);
       
   128  if (flagrpline) substdio_bputs(&ssout,rpline);
       
   129  if (flagdtline) substdio_bputs(&ssout,dtline);
       
   130  if (substdio_copy(&ssout,&ssin) == -2) die_read();
       
   131  substdio_flush(&ssout);
       
   132  close(pi[1]);
       
   133 
       
   134  if (wait_pid(&wstat,pid) == -1) die_temp();
       
   135  if (wait_crashed(wstat)) die_temp();
       
   136  _exit(wait_exitcode(wstat));
       
   137 }