chiark / gitweb /
8e76485a91c37e1f49b096f7ec19f6b47757b63a
[qmail] / preline.c
1 #include "fd.h"
2 #include "sgetopt.h"
3 #include "readwrite.h"
4 #include "subfd.h"
5 #include "substdio.h"
6 #include "exit.h"
7 #include "fork.h"
8 #include "wait.h"
9 #include "env.h"
10 #include "sig.h"
11 #include "error.h"
12
13 void die(e,s) int e; char *s; { substdio_putsflush(subfderr,s); _exit(e); }
14 void die_usage() { die(100,"preline: fatal: incorrect usage\n"); }
15 void die_temp() { die(111,"preline: fatal: temporary problem\n"); }
16 void die_read() { die(111,"preline: fatal: unable to read message\n"); }
17 void die_badcmd() { die(100,"preline: fatal: command not found\n"); }
18
19 int flagufline = 1; char *ufline;
20 int flagrpline = 1; char *rpline;
21 int flagdtline = 1; char *dtline;
22
23 substdio ssout;
24 char outbuf[SUBSTDIO_OUTSIZE];
25 substdio ssin;
26 char inbuf[SUBSTDIO_INSIZE];
27
28 void main(argc,argv)
29 int argc;
30 char **argv;
31 {
32  int opt;
33  int pi[2];
34  int pid;
35  int wstat;
36
37  sig_pipeignore();
38
39  if (!(ufline = env_get("UFLINE"))) die_usage();
40  if (!(rpline = env_get("RPLINE"))) die_usage();
41  if (!(dtline = env_get("DTLINE"))) die_usage();
42
43  while ((opt = getopt(argc,argv,"frdFRD")) != opteof)
44    switch(opt)
45     {
46      case 'f': flagufline = 0; break;
47      case 'r': flagrpline = 0; break;
48      case 'd': flagdtline = 0; break;
49      case 'F': flagufline = 1; break;
50      case 'R': flagrpline = 1; break;
51      case 'D': flagdtline = 1; break;
52      default:
53        _exit(100);
54     }
55  argc -= optind;
56  argv += optind;
57  if (!*argv) die_usage();
58
59  if (pipe(pi) == -1) die_temp();
60
61  switch(pid = fork())
62   {
63    case -1:
64      die_temp();
65    case 0:
66      close(pi[1]);
67      if (fd_move(0,pi[0])) die_temp();
68      sig_pipedefault();
69      execvp(*argv,argv);
70      if (error_temp(errno)) die_temp();
71      die_badcmd();
72   }
73  close(pi[0]);
74
75  substdio_fdbuf(&ssout,write,pi[1],outbuf,sizeof(outbuf));
76  substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
77  if (flagufline) substdio_bputs(&ssout,ufline);
78  if (flagrpline) substdio_bputs(&ssout,rpline);
79  if (flagdtline) substdio_bputs(&ssout,dtline);
80  if (substdio_copy(&ssout,&ssin) == -2) die_read();
81  substdio_flush(&ssout);
82  close(pi[1]);
83
84  if (wait_pid(&wstat,pid) == -1) die_temp();
85  if (wait_crashed(wstat)) die_temp();
86  _exit(wait_exitcode(wstat));
87 }