2 * Copyright 2001-2005 Internet2
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * shar.cpp -- the shibd "main" code. All the functionality is elsewhere
20 * Created By: Derek Atkins <derek@ihtfp.com>
25 // eventually we might be able to support autoconf via cygwin...
26 #if defined (_MSC_VER) || defined(__BORLANDC__)
27 # include "config_win32.h"
34 #include <sys/select.h>
41 #include "shar-utils.h"
45 using namespace shibboleth;
46 using namespace shibtarget;
47 using namespace shibd::logging;
50 # define FD_SETSIZE 1024
53 extern "C" void shibrpc_prog_2(struct svc_req* rqstp, register SVCXPRT* transp);
55 // Declare a "MemoryListener" that our server methods will forward their work to.
56 IListener* g_MemoryListener = NULL;
59 const char* shar_config = NULL;
60 const char* shar_schemadir = NULL;
61 bool shar_checkonly = false;
62 bool shar_version = false;
63 static int unlink_socket = 0;
64 const char* pidfile = NULL;
66 static bool new_connection(IListener::ShibSocket& listener, const Iterator<ShibRPCProtocols>& protos)
68 IListener::ShibSocket sock;
70 // Accept the connection.
71 if (!ShibTargetConfig::getConfig().getINI()->getListener()->accept(listener, sock))
74 // We throw away the result because the children manage themselves...
76 new SharChild(sock,protos);
79 saml::NDC ndc("new_connection");
80 Category& log=Category::getInstance("shibd");
81 log.crit("error starting new child thread to service request");
87 static void shar_svc_run(IListener::ShibSocket& listener, const Iterator<ShibRPCProtocols>& protos)
90 saml::NDC ndc("shar_svc_run");
92 Category& log=Category::getInstance("shibd");
97 FD_SET(listener, &readfds);
98 struct timeval tv = { 0, 0 };
101 switch (select(listener + 1, &readfds, 0, 0, &tv)) {
107 if (errno == EINTR) continue;
108 SHARUtils::log_error();
109 log.error("select() on main listener socket failed");
116 if (!new_connection(listener, protos))
117 log.crit("new_connection failed");
120 log.info("shar_svc_run ended");
125 //#include <CRTDBG.H>
127 #define nNoMansLandSize 4
128 typedef struct _CrtMemBlockHeader
130 struct _CrtMemBlockHeader * pBlockHeaderNext;
131 struct _CrtMemBlockHeader * pBlockHeaderPrev;
137 unsigned char gap[nNoMansLandSize];
139 * unsigned char data[nDataSize];
140 * unsigned char anotherGap[nNoMansLandSize];
142 } _CrtMemBlockHeader;
145 int MyAllocHook(int nAllocType, void *pvData,
146 size_t nSize, int nBlockUse, long lRequest,
147 const unsigned char * szFileName, int nLine)
149 if ( nBlockUse == _CRT_BLOCK )
151 if (nAllocType == _HOOK_FREE) {
152 _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);
153 if (ptr->nDataSize == 8192)
154 fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize);
156 else if (nAllocType == _HOOK_ALLOC && nSize == 8192)
157 fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);
162 int real_main(int preinit)
164 static IListener::ShibSocket sock;
165 ShibRPCProtocols protos[1] = {
166 { SHIBRPC_PROG, SHIBRPC_VERS_2, shibrpc_prog_2 }
169 ShibTargetConfig& conf=ShibTargetConfig::getConfig();
172 // initialize the shib-target library
174 ShibTargetConfig::Listener |
175 ShibTargetConfig::Caching |
176 ShibTargetConfig::Metadata |
177 ShibTargetConfig::Trust |
178 ShibTargetConfig::Credentials |
179 ShibTargetConfig::AAP |
180 ShibTargetConfig::GlobalExtensions |
181 (shar_checkonly ? (ShibTargetConfig::LocalExtensions | ShibTargetConfig::RequestMapper) : ShibTargetConfig::Logging)
184 shar_config=getenv("SHIBCONFIG");
186 shar_schemadir=getenv("SHIBSCHEMAS");
188 shar_schemadir=SHIB_SCHEMAS;
190 shar_config=SHIB_CONFIG;
191 if (!conf.init(shar_schemadir) || !conf.load(shar_config)) {
192 fprintf(stderr, "configuration is invalid, see console for specific problems\n");
196 // If just a test run, bail.
197 if (shar_checkonly) {
198 fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
202 // Build an internal "listener" to handle the work.
203 IPlugIn* plugin=SAMLConfig::getConfig().getPlugMgr().newPlugin(shibtarget::XML::MemoryListenerType,NULL);
204 g_MemoryListener=dynamic_cast<IListener*>(plugin);
205 if (!g_MemoryListener) {
207 fprintf(stderr, "MemoryListener plugin failed to load");
212 const IListener* listener=conf.getINI()->getListener();
214 // Create the SHAR listener socket
215 if (!listener->create(sock)) {
216 delete g_MemoryListener;
221 // Bind to the proper port
222 if (!listener->bind(sock)) {
223 delete g_MemoryListener;
228 // Initialize the SHAR Utilitites
233 //_CrtSetAllocHook(MyAllocHook);
236 if (!shar_checkonly) {
237 shar_svc_run(sock, ArrayIterator<ShibRPCProtocols>(protos,1));
239 // Finalize the SHAR, close all clients
241 conf.getINI()->getListener()->close(sock);
244 delete g_MemoryListener;
252 static void term_handler(int arg)
257 static int setup_signals(void)
259 NDC ndc("setup_signals");
262 memset(&sa, 0, sizeof (sa));
263 sa.sa_handler = SIG_IGN;
264 sa.sa_flags = SA_RESTART;
266 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
267 SHARUtils::log_error();
271 memset(&sa, 0, sizeof (sa));
272 sa.sa_handler = term_handler;
273 sa.sa_flags = SA_RESTART;
275 if (sigaction(SIGHUP, &sa, NULL) < 0) {
276 SHARUtils::log_error();
279 if (sigaction(SIGINT, &sa, NULL) < 0) {
280 SHARUtils::log_error();
283 if (sigaction(SIGQUIT, &sa, NULL) < 0) {
284 SHARUtils::log_error();
287 if (sigaction(SIGTERM, &sa, NULL) < 0) {
288 SHARUtils::log_error();
294 static void usage(char* whoami)
296 fprintf(stderr, "usage: %s [-fcdt]\n", whoami);
297 fprintf(stderr, " -c\tconfig file to use.\n");
298 fprintf(stderr, " -d\tschema directory to use.\n");
299 fprintf(stderr, " -t\tcheck configuration file for problems.\n");
300 fprintf(stderr, " -f\tforce removal of listener socket.\n");
301 fprintf(stderr, " -p\tpid file to use.\n");
302 fprintf(stderr, " -v\tprint software version.\n");
303 fprintf(stderr, " -h\tprint this help message.\n");
307 static int parse_args(int argc, char* argv[])
311 while ((opt = getopt(argc, argv, "c:d:p:ftvh")) > 0) {
317 shar_schemadir=optarg;
338 int main(int argc, char *argv[])
340 IListener::ShibSocket sock;
341 ShibRPCProtocols protos[] = {
342 { SHIBRPC_PROG, SHIBRPC_VERS_2, shibrpc_prog_2 }
345 if (parse_args(argc, argv) != 0)
347 else if (shar_version) {
348 fprintf(stdout, PACKAGE_STRING);
352 if (setup_signals() != 0)
356 shar_config=getenv("SHIBCONFIG");
358 shar_schemadir=getenv("SHIBSCHEMAS");
360 shar_schemadir=SHIB_SCHEMAS;
362 shar_config=SHIB_CONFIG;
364 // initialize the shib-target library
365 ShibTargetConfig& conf=ShibTargetConfig::getConfig();
367 ShibTargetConfig::Listener |
368 ShibTargetConfig::Caching |
369 ShibTargetConfig::Metadata |
370 ShibTargetConfig::Trust |
371 ShibTargetConfig::Credentials |
372 ShibTargetConfig::AAP |
373 ShibTargetConfig::GlobalExtensions |
374 (shar_checkonly ? (ShibTargetConfig::LocalExtensions | ShibTargetConfig::RequestMapper) : ShibTargetConfig::Logging)
376 if (!conf.init(shar_schemadir) || !conf.load(shar_config)) {
377 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
382 fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
385 // Build an internal "listener" to handle the work.
386 IPlugIn* plugin=SAMLConfig::getConfig().getPlugMgr().newPlugin(shibtarget::XML::MemoryListenerType,NULL);
387 g_MemoryListener=dynamic_cast<IListener*>(plugin);
388 if (!g_MemoryListener) {
390 fprintf(stderr, "MemoryListener plugin failed to load");
395 const IListener* listener=conf.getINI()->getListener();
397 // Create the SHAR listener socket
398 if (!listener->create(sock)) {
399 delete g_MemoryListener;
404 // Bind to the proper port
405 if (!listener->bind(sock, unlink_socket==1)) {
406 delete g_MemoryListener;
411 // Write the pid file
413 FILE* pidf = fopen(pidfile, "w");
415 fprintf(pidf, "%d\n", getpid());
418 perror(pidfile); // keep running though
422 // Initialize the SHAR Utilitites
426 shar_svc_run(sock, ArrayIterator<ShibRPCProtocols>(protos,1));
428 /* Finalize the SHAR, close all clients */
431 listener->close(sock);