+/* ***************************************************************************
+ CGI to SCGI Bridge
+
+ (c) Konrad Rosenbaum, 2010
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program (file COPYING.GPL).
+ If not, see <http://www.gnu.org/licenses/>.
+
+******************************************************************************/
+
#include <errno.h>
#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
while(*evn){
int l1,l2;
if(strcmp(*evn,"CONTENT_LENGTH")==0)continue;
+ if(strncmp(*evn,"SCGI",4)==0)continue;
l1=strlen(*evn)+1;
evc=getenv(*evn);
l2=strlen(evc)+1;
}while(1);
}
+char*scgifile=0;
+char*scgihost=0;
+char*scgiport=0;
+
+void openFile()
+{
+ if(scgifile==0)return;
+ scfd=open(scgifile,O_RDWR);
+}
+
+void openNet()
+{
+ int sfd,port;
+ char*ep;
+ struct addrinfo *ai,*rai;
+ //sanity checks and get port
+ if(scgihost==0 || scgiport==0)return;
+ port=strtol(scgiport,&ep,10);
+ if(*ep!=0)return;
+ if(port<=0 || port > 0xffff)return;
+ //resolve name
+ if(getaddrinfo(scgihost,0,0,&ai)!=0)return;
+ rai=ai;
+ if(ai==0)return;
+ //get matching socket
+ for(;ai;ai=ai->ai_next){
+ //get a socket
+ if(ai->ai_family!=AF_INET && ai->ai_family!=AF_INET6)continue;
+ sfd=socket(ai->ai_family,SOCK_STREAM,0);
+ if(sfd<0)continue;
+ //IPv4?
+ if(ai->ai_family==AF_INET){
+ struct sockaddr_in sa;
+ memset(&sa,0,sizeof(sa));
+ sa.sin_family=AF_INET;
+ sa.sin_port=htons(port);
+ memcpy(&sa.sin_addr, &((struct sockaddr_in*)(ai->ai_addr))->sin_addr, sizeof(sa.sin_addr));
+ if(connect(sfd,(struct sockaddr*)&sa,sizeof(sa))==0){
+ scfd=sfd;
+ break;
+ }else
+ close(sfd);
+ }else{
+ //IPv6
+ struct sockaddr_in6 sa;
+ memset(&sa,0,sizeof(sa));
+ sa.sin6_family=AF_INET6;
+ sa.sin6_port=htons(port);
+ memcpy(&sa.sin6_addr, &((struct sockaddr_in6*)(ai->ai_addr))->sin6_addr, sizeof(sa.sin6_addr));
+ if(connect(sfd,(struct sockaddr*)&sa,sizeof(sa))==0){
+ scfd=sfd;
+ break;
+ }else
+ close(sfd);
+ }
+ }
+ //free info
+ freeaddrinfo(rai);
+}
int main(int argc,char**argv)
{
- //open connection
- if(argc!=2){
- fprintf(stderr,"Error: usage %s socket\n",*argv);
+ //check argument list size
+ if(argc>3){
+ fprintf(stderr,"Error: usage %s [socket] | [host port]\n",*argv);
printf(ERROR);
return 1;
}
- scfd=open(argv[1],O_RDWR);
+ //check environment
+ scgifile=getenv("SCGI_FILE");
+ scgihost=getenv("SCGI_HOST");
+ scgiport=getenv("SCGI_PORT");
+ //overide env by args
+ if(argc==2){
+ scgifile=argv[1];
+ }
+ if(argc==3){
+ scgihost=argv[1];
+ scgiport=argv[2];
+ }
+ //get connection
+ openFile();
+ if(scfd<0)openNet();
if(scfd<0){
fprintf(stderr,"Error: cannot open socket\n");
printf(ERROR);