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 SHAR "main" code. All the functionality is elsewhere
19 * (in case you want to turn this into a library later).
21 * Created By: Derek Atkins <derek@ihtfp.com>
26 // eventually we might be able to support autoconf via cygwin...
27 #if defined (_MSC_VER) || defined(__BORLANDC__)
28 # include "config_win32.h"
35 #include <sys/select.h>
42 #include "shar-utils.h"
43 #include <log4cpp/Category.hh>
48 using namespace shibboleth;
49 using namespace shibtarget;
50 using namespace log4cpp;
53 # define FD_SETSIZE 1024
56 extern "C" void shibrpc_prog_2(struct svc_req* rqstp, register SVCXPRT* transp);
58 // Declare a "MemoryListener" that our server methods will forward their work to.
59 IListener* g_MemoryListener = NULL;
62 const char* shar_config = NULL;
63 const char* shar_schemadir = NULL;
64 bool shar_checkonly = false;
65 static int unlink_socket = 0;
67 static bool new_connection(IListener::ShibSocket& listener, const Iterator<ShibRPCProtocols>& protos)
69 IListener::ShibSocket sock;
71 // Accept the connection.
72 if (!ShibTargetConfig::getConfig().getINI()->getListener()->accept(listener, sock))
75 // We throw away the result because the children manage themselves...
77 new SharChild(sock,protos);
80 saml::NDC ndc("new_connection");
81 Category& log=Category::getInstance("shibd");
82 log.crit("error starting new child thread to service request");
88 static void shar_svc_run(IListener::ShibSocket& listener, const Iterator<ShibRPCProtocols>& protos)
91 saml::NDC ndc("shar_svc_run");
93 Category& log=Category::getInstance("shibd");
98 FD_SET(listener, &readfds);
99 struct timeval tv = { 0, 0 };
102 switch (select(listener + 1, &readfds, 0, 0, &tv)) {
108 if (errno == EINTR) continue;
109 SHARUtils::log_error();
110 log.error("select() on main listener socket failed");
117 if (!new_connection(listener, protos))
118 log.crit("new_connection failed");
121 log.info("shar_svc_run ended");
126 //#include <CRTDBG.H>
128 #define nNoMansLandSize 4
129 typedef struct _CrtMemBlockHeader
131 struct _CrtMemBlockHeader * pBlockHeaderNext;
132 struct _CrtMemBlockHeader * pBlockHeaderPrev;
138 unsigned char gap[nNoMansLandSize];
140 * unsigned char data[nDataSize];
141 * unsigned char anotherGap[nNoMansLandSize];
143 } _CrtMemBlockHeader;
146 int MyAllocHook(int nAllocType, void *pvData,
147 size_t nSize, int nBlockUse, long lRequest,
148 const unsigned char * szFileName, int nLine)
150 if ( nBlockUse == _CRT_BLOCK )
152 if (nAllocType == _HOOK_FREE) {
153 _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);
154 if (ptr->nDataSize == 8192)
155 fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize);
157 else if (nAllocType == _HOOK_ALLOC && nSize == 8192)
158 fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);
163 int real_main(int preinit)
165 static IListener::ShibSocket sock;
166 ShibRPCProtocols protos[1] = {
167 { SHIBRPC_PROG, SHIBRPC_VERS_2, shibrpc_prog_2 }
170 ShibTargetConfig& conf=ShibTargetConfig::getConfig();
173 // initialize the shib-target library
175 ShibTargetConfig::Listener |
176 ShibTargetConfig::Caching |
177 ShibTargetConfig::Metadata |
178 ShibTargetConfig::Trust |
179 ShibTargetConfig::Credentials |
180 ShibTargetConfig::AAP |
181 ShibTargetConfig::GlobalExtensions |
182 (shar_checkonly ? (ShibTargetConfig::LocalExtensions | ShibTargetConfig::RequestMapper) : ShibTargetConfig::Logging)
185 shar_config=getenv("SHIBCONFIG");
187 shar_schemadir=getenv("SHIBSCHEMAS");
189 shar_schemadir=SHIB_SCHEMAS;
191 shar_config=SHIB_CONFIG;
192 if (!conf.init(shar_schemadir) || !conf.load(shar_config)) {
193 fprintf(stderr, "configuration is invalid, see console for specific problems\n");
197 // If just a test run, bail.
198 if (shar_checkonly) {
199 fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
203 // Build an internal "listener" to handle the work.
204 IPlugIn* plugin=SAMLConfig::getConfig().getPlugMgr().newPlugin(shibtarget::XML::MemoryListenerType,NULL);
205 g_MemoryListener=dynamic_cast<IListener*>(plugin);
206 if (!g_MemoryListener) {
208 fprintf(stderr, "MemoryListener plugin failed to load");
213 const IListener* listener=conf.getINI()->getListener();
215 // Create the SHAR listener socket
216 if (!listener->create(sock)) {
217 delete g_MemoryListener;
222 // Bind to the proper port
223 if (!listener->bind(sock)) {
224 delete g_MemoryListener;
229 // Initialize the SHAR Utilitites
234 //_CrtSetAllocHook(MyAllocHook);
237 if (!shar_checkonly) {
238 shar_svc_run(sock, ArrayIterator<ShibRPCProtocols>(protos,1));
239 fprintf(stdout,"shar_svc_run returned\n");
241 // Finalize the SHAR, close all clients
243 conf.getINI()->getListener()->close(sock);
246 delete g_MemoryListener;
248 fprintf(stdout, "shibd shutdown complete\n");
255 static void term_handler(int arg)
260 static int setup_signals(void)
262 NDC ndc("setup_signals");
265 memset(&sa, 0, sizeof (sa));
266 sa.sa_handler = SIG_IGN;
267 sa.sa_flags = SA_RESTART;
269 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
270 SHARUtils::log_error();
274 memset(&sa, 0, sizeof (sa));
275 sa.sa_handler = term_handler;
276 sa.sa_flags = SA_RESTART;
278 if (sigaction(SIGHUP, &sa, NULL) < 0) {
279 SHARUtils::log_error();
282 if (sigaction(SIGINT, &sa, NULL) < 0) {
283 SHARUtils::log_error();
286 if (sigaction(SIGQUIT, &sa, NULL) < 0) {
287 SHARUtils::log_error();
290 if (sigaction(SIGTERM, &sa, NULL) < 0) {
291 SHARUtils::log_error();
297 static void usage(char* whoami)
299 fprintf(stderr, "usage: %s [-fcdt]\n", whoami);
300 fprintf(stderr, " -c\tconfig file to use.\n");
301 fprintf(stderr, " -d\tschema directory to use.\n");
302 fprintf(stderr, " -t\tcheck configuration file for problems.\n");
303 fprintf(stderr, " -f\tforce removal of listener socket.\n");
304 fprintf(stderr, " -h\tprint this help message.\n");
308 static int parse_args(int argc, char* argv[])
312 while ((opt = getopt(argc, argv, "c:d:fth")) > 0) {
318 shar_schemadir=optarg;
333 int main(int argc, char *argv[])
335 IListener::ShibSocket sock;
336 ShibRPCProtocols protos[] = {
337 { SHIBRPC_PROG, SHIBRPC_VERS_2, shibrpc_prog_2 }
340 if (setup_signals() != 0)
343 if (parse_args(argc, argv) != 0)
347 shar_config=getenv("SHIBCONFIG");
349 shar_schemadir=getenv("SHIBSCHEMAS");
351 shar_schemadir=SHIB_SCHEMAS;
353 shar_config=SHIB_CONFIG;
355 // initialize the shib-target library
356 ShibTargetConfig& conf=ShibTargetConfig::getConfig();
358 ShibTargetConfig::Listener |
359 ShibTargetConfig::Caching |
360 ShibTargetConfig::Metadata |
361 ShibTargetConfig::Trust |
362 ShibTargetConfig::Credentials |
363 ShibTargetConfig::AAP |
364 ShibTargetConfig::GlobalExtensions |
365 (shar_checkonly ? (ShibTargetConfig::LocalExtensions | ShibTargetConfig::RequestMapper) : ShibTargetConfig::Logging)
367 if (!conf.init(shar_schemadir) || !conf.load(shar_config)) {
368 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
373 fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
376 // Build an internal "listener" to handle the work.
377 IPlugIn* plugin=SAMLConfig::getConfig().getPlugMgr().newPlugin(shibtarget::XML::MemoryListenerType,NULL);
378 g_MemoryListener=dynamic_cast<IListener*>(plugin);
379 if (!g_MemoryListener) {
381 fprintf(stderr, "MemoryListener plugin failed to load");
386 const IListener* listener=conf.getINI()->getListener();
388 // Create the SHAR listener socket
389 if (!listener->create(sock)) {
390 delete g_MemoryListener;
395 // Bind to the proper port
396 if (!listener->bind(sock, unlink_socket==1)) {
397 delete g_MemoryListener;
402 // Initialize the SHAR Utilitites
406 shar_svc_run(sock, ArrayIterator<ShibRPCProtocols>(protos,1));
408 /* Finalize the SHAR, close all clients */
410 fprintf(stderr, "shar utils finalized\n");
412 listener->close(sock);
413 fprintf(stderr, "shib socket closed\n");
417 fprintf(stderr, "shibd shutdown complete\n");