2 * Copyright 2001-2010 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 * shibd.cpp -- the shibd "main" code. All the functionality is elsewhere
22 // eventually we might be able to support autoconf via cygwin...
23 #if defined (_MSC_VER) || defined(__BORLANDC__)
24 # include "config_win32.h"
30 # define _CRT_NONSTDC_NO_DEPRECATE 1
31 # define _CRT_SECURE_NO_DEPRECATE 1
34 #include <shibsp/SPConfig.h>
38 #include <sys/select.h>
43 #include <shibsp/ServiceProvider.h>
44 #include <shibsp/remoting/ListenerService.h>
45 #include <xercesc/util/XMLUniDefs.hpp>
46 #include <xmltooling/XMLToolingConfig.h>
47 #include <xmltooling/util/XMLConstants.h>
48 #include <xmltooling/util/XMLHelper.h>
50 using namespace shibsp;
51 using namespace xmltooling;
54 bool shibd_shutdown = false;
55 const char* shar_config = nullptr;
56 const char* shar_schemadir = nullptr;
57 const char* shar_prefix = nullptr;
58 bool shar_checkonly = false;
59 bool shar_version = false;
60 static bool unlink_socket = false;
61 const char* pidfile = nullptr;
67 #define nNoMansLandSize 4
68 typedef struct _CrtMemBlockHeader
70 struct _CrtMemBlockHeader * pBlockHeaderNext;
71 struct _CrtMemBlockHeader * pBlockHeaderPrev;
77 unsigned char gap[nNoMansLandSize];
79 * unsigned char data[nDataSize];
80 * unsigned char anotherGap[nNoMansLandSize];
85 int MyAllocHook(int nAllocType, void *pvData,
86 size_t nSize, int nBlockUse, long lRequest,
87 const unsigned char * szFileName, int nLine)
89 if ( nBlockUse == _CRT_BLOCK )
91 if (nAllocType == _HOOK_FREE) {
92 _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);
93 if (ptr->nDataSize == 8192)
94 fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize);
96 else if (nAllocType == _HOOK_ALLOC && nSize == 8192)
97 fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);
102 int real_main(int preinit)
104 SPConfig& conf=SPConfig::getConfig();
107 // Initialize the SP library.
113 SPConfig::Credentials |
114 SPConfig::AttributeResolution |
116 SPConfig::OutOfProcess |
117 (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
119 if (!conf.init(shar_schemadir, shar_prefix)) {
120 fprintf(stderr, "configuration is invalid, see console for specific problems\n");
124 if (!conf.instantiate(shar_config)) {
125 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
130 // If just a test run, bail.
131 if (shar_checkonly) {
132 fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
138 //_CrtSetAllocHook(MyAllocHook);
140 if (!shar_checkonly) {
142 ListenerService* listener = conf.getServiceProvider()->getListenerService();
143 if (!listener->init(unlink_socket)) {
144 fprintf(stderr, "listener failed to initialize\n");
148 else if (!listener->run(&shibd_shutdown)) {
149 fprintf(stderr, "listener failed during service\n");
165 bool shibd_running = false;
166 bool daemonize = true;
168 static void term_handler(int arg)
170 shibd_shutdown = true;
173 static void run_handler(int arg)
175 shibd_running = true;
178 static void child_handler(int arg)
180 // Terminate the parent's wait/sleep if the newly born daemon dies early.
183 static int setup_signals(void)
186 memset(&sa, 0, sizeof (sa));
187 sa.sa_handler = SIG_IGN;
188 sa.sa_flags = SA_RESTART;
190 if (sigaction(SIGPIPE, &sa, nullptr) < 0) {
194 memset(&sa, 0, sizeof (sa));
195 sa.sa_handler = term_handler;
196 sa.sa_flags = SA_RESTART;
198 if (sigaction(SIGHUP, &sa, nullptr) < 0) {
201 if (sigaction(SIGINT, &sa, nullptr) < 0) {
204 if (sigaction(SIGQUIT, &sa, nullptr) < 0) {
207 if (sigaction(SIGTERM, &sa, nullptr) < 0) {
212 memset(&sa, 0, sizeof (sa));
213 sa.sa_handler = run_handler;
215 if (sigaction(SIGUSR1, &sa, nullptr) < 0) {
219 memset(&sa, 0, sizeof (sa));
220 sa.sa_handler = child_handler;
222 if (sigaction(SIGCHLD, &sa, nullptr) < 0) {
230 static void usage(char* whoami)
232 fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami);
233 fprintf(stderr, " -d\tinstallation prefix to use.\n");
234 fprintf(stderr, " -c\tconfig file to use.\n");
235 fprintf(stderr, " -x\tXML schema catalogs to use.\n");
236 fprintf(stderr, " -t\ttest configuration file for problems.\n");
237 fprintf(stderr, " -f\tforce removal of listener socket.\n");
238 fprintf(stderr, " -F\tstay in the foreground.\n");
239 fprintf(stderr, " -p\tpid file to use.\n");
240 fprintf(stderr, " -w\tseconds to wait for successful daemonization.\n");
241 fprintf(stderr, " -v\tprint software version.\n");
242 fprintf(stderr, " -h\tprint this help message.\n");
246 static int parse_args(int argc, char* argv[])
250 while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) {
259 shar_schemadir=optarg;
262 unlink_socket = true;
279 daemon_wait = atoi(optarg);
280 if (daemon_wait <= 0)
290 int main(int argc, char *argv[])
292 if (parse_args(argc, argv) != 0)
294 else if (shar_version) {
295 fprintf(stdout, PACKAGE_STRING"\n");
299 if (setup_signals() != 0)
302 // initialize the shib-target library
303 SPConfig& conf=SPConfig::getConfig();
309 SPConfig::Credentials |
310 SPConfig::AttributeResolution |
312 SPConfig::OutOfProcess |
313 (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
315 if (!conf.init(shar_schemadir, shar_prefix)) {
316 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
321 // We must fork() early, while we're single threaded.
322 // StorageService cleanup thread is about to start.
331 exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);
335 if (!conf.instantiate(shar_config)) {
336 fprintf(stderr, "configuration is invalid, check console for specific problems\n");
342 fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
344 // Init the listener.
345 ListenerService* listener = conf.getServiceProvider()->getListenerService();
346 if (!listener->init(unlink_socket)) {
347 fprintf(stderr, "listener failed to initialize\n");
353 if (setsid() == -1) {
357 if (chdir("/") == -1) {
358 perror("chdir to root");
363 FILE* pidf = fopen(pidfile, "w");
365 fprintf(pidf, "%d\n", getpid());
373 freopen("/dev/null", "r", stdin);
374 freopen("/dev/null", "w", stdout);
375 freopen("/dev/null", "w", stderr);
377 // Signal our parent that we are A-OK.
378 kill(getppid(), SIGUSR1);
382 if (!listener->run(&shibd_shutdown)) {
383 fprintf(stderr, "listener failure during service\n");
386 if (daemonize && pidfile)
394 if (daemonize && pidfile)