1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
#define NOLOGATALL
#include "../source/acbuf.cc"
#include "../include/sockio.h"
#include "../include/fileio.h"
#include <unistd.h>
#include <sys/select.h>
#include <signal.h>
namespace acng{
namespace cfg
{
int nettimeout=60;
}
}
int main(int argc, char **argv)
{
using namespace acng;
signal(SIGPIPE, SIG_IGN);
acbuf bufToD, bufFromD;
int in=fileno(stdin);
int out=fileno(stdout);
if (in<0 || out<0)
return -1; // hm?!
if (argc<2)
{
printf("ERROR: Missing socket path argument, check inetd.conf.\n");
return 1;
}
size_t pLen=strlen(argv[1]);
if (pLen>107)
{
printf("ERROR: Bad socket path, too long.\n");
return -2;
}
struct stat stinfo;
if (0!=stat(argv[1], &stinfo) || !S_ISSOCK(stinfo.st_mode))
{
printf("HTTP/1.1 500 ERROR: Socket file missing or in bad state. Check the command lines.\r\n\r\n");
return 2;
}
struct sockaddr_storage ss;
socklen_t slen = sizeof(ss);
char hbuf[NI_MAXHOST];
#if 1
if (0!=getpeername(in, (struct sockaddr *)&ss, &slen))
{
printf("ERROR: stdin is not a socket.\n");
return 1;
}
if (getnameinfo((struct sockaddr*) &ss, sizeof(ss), hbuf, sizeof(hbuf),
nullptr, 0, NI_NUMERICHOST))
{
printf("ERROR: could not resolve hostname\n");
return 1;
}
#else
strcpy(hbuf, "localhost");
#endif
bufToD.setsize(4000);
bufFromD.setsize(16000);
int n=snprintf(bufToD.wptr(), bufToD.freecapa(),
"GET / HTTP/1.1\r\nX-Original-Source: %s\r\n\r\n", hbuf);
if (n<0 || n==(int)bufToD.freecapa()) // weird... too long?
return 3;
bufToD.got(n);
int s=socket(PF_UNIX, SOCK_STREAM, 0);
if(s<0)
return 4;
struct sockaddr_un addr;
addr.sun_family=PF_UNIX;
strcpy(addr.sun_path, argv[1]);
socklen_t adlen = pLen+1+offsetof(struct sockaddr_un, sun_path);
if ( 0!=connect(s, (struct sockaddr*)&addr, adlen))
{
printf("HTTP/1.1 500 ERROR: Unable to attach to the local daemon: %s\r\n\r\n", strerror(errno));
return 5;
}
int maxfd=1+std::max(in, std::max(out, s));
while (true)
{
fd_set rfds, wfds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
if(bufToD.size()>0)
FD_SET(s, &wfds);
if(bufFromD.size()>0)
FD_SET(out, &wfds);
if(bufFromD.freecapa()>0)
FD_SET(s, &rfds);
if(bufToD.freecapa()>0)
FD_SET(in, &rfds);
int nReady=select(maxfd, &rfds, &wfds, nullptr, nullptr);
if (nReady<0)
{
fputs("Select failure.\n", stdout);
exit(1);
}
if(FD_ISSET(s, &wfds))
{
if(bufToD.syswrite(s)<0)
return 1;
}
if(FD_ISSET(out, &wfds))
{
if(bufFromD.syswrite(out)<0)
return 1;
}
if(FD_ISSET(s, &rfds))
{
if(bufFromD.sysread(s)<=0)
goto finished;
}
if(FD_ISSET(in, &rfds))
{
if(bufToD.sysread(in)<=0)
goto finished;
}
}
finished:
forceclose(s);
::shutdown(s, SHUT_RDWR);
return 0;
}
|