chiark / gitweb /
Merge branches 'idx/verh' and 'idx/qmqpc'
[qmail] / tcp-env.c
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <sys/param.h>
4 #include <netinet/in.h>
5 #include "sig.h"
6 #include "stralloc.h"
7 #include "str.h"
8 #include "env.h"
9 #include "fmt.h"
10 #include "scan.h"
11 #include "subgetopt.h"
12 #include "ip.h"
13 #include "dns.h"
14 #include "byte.h"
15 #include "remoteinfo.h"
16 #include "exit.h"
17 #include "case.h"
18
19 void die() { _exit(111); }
20
21 struct sockaddr_in salocal;
22 unsigned long localport;
23 struct ip_address iplocal;
24 stralloc localname = {0};
25
26 struct sockaddr_in saremote;
27 unsigned long remoteport;
28 struct ip_address ipremote;
29 stralloc remotename = {0};
30
31 char temp[IPFMT + FMT_ULONG];
32
33 void main(argc,argv)
34 int argc;
35 char *argv[];
36 {
37  int dummy;
38  char *proto;
39  int opt;
40  int flagremoteinfo;
41  unsigned long timeout;
42
43  sig_pipeignore();
44
45  flagremoteinfo = 1;
46  timeout = 30;
47  while ((opt = sgopt(argc,argv,"rRt:")) != sgoptdone)
48    switch(opt)
49     {
50      case 'r': flagremoteinfo = 1; break;
51      case 'R': flagremoteinfo = 0; break;
52      case 't': scan_ulong(sgoptarg,&timeout); break;
53     }
54
55  argv += sgoptind;
56  argc -= sgoptind;
57
58  if (argc < 1) die();
59  if (!env_init()) die();
60
61  proto = env_get("PROTO");
62  if (!proto || str_diff(proto,"TCP"))
63   {
64    if (!env_put("PROTO=TCP")) die();
65
66    dummy = sizeof(salocal);
67    if (getsockname(0,(struct sockaddr *) &salocal,&dummy) == -1) die();
68
69    localport = ntohs(salocal.sin_port);
70    temp[fmt_ulong(temp,localport)] = 0;
71    if (!env_put2("TCPLOCALPORT",temp)) die();
72
73    byte_copy(&iplocal,4,&salocal.sin_addr);
74    temp[ip_fmt(temp,&iplocal)] = 0;
75    if (!env_put2("TCPLOCALIP",temp)) die();
76
77    switch(dns_ptr(&localname,&iplocal))
78     {
79      case DNS_MEM: die();
80      case DNS_SOFT:
81        if (!stralloc_copys(&localname,"softdnserror")) die();
82      case 0:
83        if (!stralloc_0(&localname)) die();
84        case_lowers(localname.s);
85        if (!env_put2("TCPLOCALHOST",localname.s)) die();
86        break;
87      default:
88        if (!env_unset("TCPLOCALHOST")) die();
89     }
90
91    dummy = sizeof(saremote);
92    if (getpeername(0,(struct sockaddr *) &saremote,&dummy) == -1) die();
93
94    remoteport = ntohs(saremote.sin_port);
95    temp[fmt_ulong(temp,remoteport)] = 0;
96    if (!env_put2("TCPREMOTEPORT",temp)) die();
97
98    byte_copy(&ipremote,4,&saremote.sin_addr);
99    temp[ip_fmt(temp,&ipremote)] = 0;
100    if (!env_put2("TCPREMOTEIP",temp)) die();
101
102    switch(dns_ptr(&remotename,&ipremote))
103     {
104      case DNS_MEM: die();
105      case DNS_SOFT:
106        if (!stralloc_copys(&remotename,"softdnserror")) die();
107      case 0:
108        if (!stralloc_0(&remotename)) die();
109        case_lowers(remotename.s);
110        if (!env_put2("TCPREMOTEHOST",remotename.s)) die();
111        break;
112      default:
113        if (!env_unset("TCPREMOTEHOST")) die();
114     }
115
116    if (!env_unset("TCPREMOTEINFO")) die();
117    if (flagremoteinfo)
118     {
119      char *rinfo;
120      rinfo = remoteinfo_get(&ipremote,remoteport,&iplocal,localport,(int) timeout);
121      if (rinfo)
122        if (!env_put2("TCPREMOTEINFO",rinfo)) die();
123     }
124   }
125
126  sig_pipedefault();
127  execvp(*argv,argv);
128  die();
129 }