zxid
view release on metacpan or search on metacpan
zxidwspcgi.c view on Meta::CPAN
"zxidwspcgi - ID-WSF 2.0 WSP CGI - R" ZXID_REL "\n\
SAML 2.0 and ID-WSF 2.0 are standards for federated identity and web services.\n\
Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.\n\
NO WARRANTY, not even implied warranties. Licensed under Apache License v2.0\n\
See http://www.apache.org/licenses/LICENSE-2.0\n\
Send well-researched bug reports to the author. Home: zxid.org\n\
\n\
Usage: zxidwspcgi [options] (when used as CGI, no options can be supplied)\n\
-h This help message\n\
-- End of options\n\
\n\
Built-in configuration: " CONF "\n\
\n\
This C program implements a generic Web Services Provider. It is meant\n\
to be run as a cgi script from a web server. It will validate\n\
an incoming web service request and then pass it to sysadmin-supplied\n\
external program on stdin. The external program could be a shell script or\n\
a perl program - whatever you want. The external program reads the payload\n\
request from stdin and prints the payload response to stdout. zxidwspcgi\n\
handles the pipe-in - pipe-out deadlock dilemma by forking a process to\n\
perform the feeding in, while the original process will receive the\n\
stdout of the subprocess. Once entire payload response has been received,\n\
the response will be decorated with ID-WSF headers and sent as response\n\
to the original caller.\n";
char buf[256*1024]; /* *** should figure the size dynamically */
int child_in_fds[2]; /* Parent out */
int child_out_fds[2]; /* Parent in */
/*() Send data to script using child process */
/* Called by: zxidwspcgi_main */
static int zxidwspcgi_child(zxid_conf* cf, int len, char* buf, char* sid, char* nid)
{
int status;
pid_t pid;
close(0);
close(1);
if (pid = fork()) { /* Parent pumps child's input */
close(child_out_fds[0]);
close(child_out_fds[1]);
close(child_in_fds[0]);
D("Writing %d bytes to child pid=%d", len, pid);
write_all_fd(child_in_fds[1], buf, len);
D("Waiting for child pid=%d", pid);
if (waitpid(pid, &status, 0) == -1) {
perror("waitpid");
}
return status;
} else {
close(child_out_fds[0]);
close(child_in_fds[1]);
if (dup(child_in_fds[0]) != 0) {
perror("dup stdin");
return 1;
}
if (dup(child_out_fds[1]) != 1) {
perror("dup stdout");
return 1;
}
setenv("idpnid", nid, 1);
setenv("sid", sid, 1);
D("exec(%s)", cf->wspcgicmd);
execl(cf->wspcgicmd, cf->wspcgicmd); /* At least gcc-3.4.6 gives bogus "warning: not enough variable arguments to fit a sentinel [-Wformat]" on this line. AFAIK you can safely ignore the warning. --Sampo */
perror("exec");
ERR("Exec(%s) failed: errno=%d", cf->wspcgicmd, errno);
return 1;
}
return 0;
}
/*() Read from script using parent, and send resp. */
/* Called by: zxidwspcgi_main */
static int zxidwspcgi_parent(zxid_conf* cf, zxid_ses* ses, int pid)
{
struct zx_str* ss;
int got_all;
if (pid == -1) {
perror("first fork");
return 1;
}
close(child_out_fds[1]);
close(child_in_fds[0]);
close(child_in_fds[1]);
D("Reading from child writer_pid=%d", pid);
read_all_fd(child_out_fds[0], buf, sizeof(buf)-1, &got_all);
buf[got_all] = 0;
D("Got from child %d bytes", got_all);
ss = zxid_wsp_decorate(cf, ses, 0, buf);
fprintf(stdout, "CONTENT-TYPE: text/xml\r\nCONTENT-LENGTH: %d\r\n\r\n%.*s", ss->len, ss->len, ss->s);
fflush(stdout);
if (waitpid(pid, &got_all, 0) == -1) {
perror("waitpid");
}
return 0;
}
/* ============== M A I N ============== */
#ifndef zxidwspcgi_main
#define zxidwspcgi_main main
#endif
/* Called by: */
int zxidwspcgi_main(int argc, char** argv)
{
zxid_conf* cf;
zxid_ses sess;
zxid_ses* ses = &sess;
char* nid;
char* p;
char* res;
char urlbuf[256];
int got, cl=0;
char* qs;
char* qs2;
pid_t pid;
ZERO(ses, sizeof(zxid_ses));
#if 1
/* Helps debugging CGI scripts if you see stderr. */
( run in 1.884 second using v1.01-cache-2.11-cpan-98e64b0badf )