-/*\r
- * Copyright 2001-2007 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/*\r
- * shar.cpp -- the shibd "main" code. All the functionality is elsewhere\r
- *\r
- * Created By: Derek Atkins <derek@ihtfp.com>\r
- *\r
- * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $\r
- */\r
-\r
-\r
-// eventually we might be able to support autoconf via cygwin...\r
-#if defined (_MSC_VER) || defined(__BORLANDC__)\r
-# include "config_win32.h"\r
-#else\r
-# include "config.h"\r
-#endif\r
-\r
-#ifdef WIN32\r
-# define _CRT_NONSTDC_NO_DEPRECATE 1\r
-# define _CRT_SECURE_NO_DEPRECATE 1\r
-#endif\r
-\r
-#include <shibsp/SPConfig.h>\r
-\r
-#ifdef HAVE_UNISTD_H\r
-#include <unistd.h>\r
-#include <sys/select.h>\r
-#endif\r
-\r
-#include <stdio.h>\r
-#include <signal.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <shibsp/remoting/ListenerService.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-bool shibd_shutdown = false;\r
-const char* shar_config = NULL;\r
-const char* shar_schemadir = NULL;\r
-bool shar_checkonly = false;\r
-static int unlink_socket = 0;\r
-const char* pidfile = NULL;\r
-\r
-#ifdef WIN32\r
-\r
-//#include <CRTDBG.H>\r
-\r
-#define nNoMansLandSize 4\r
-typedef struct _CrtMemBlockHeader\r
-{\r
- struct _CrtMemBlockHeader * pBlockHeaderNext;\r
- struct _CrtMemBlockHeader * pBlockHeaderPrev;\r
- char * szFileName;\r
- int nLine;\r
- size_t nDataSize;\r
- int nBlockUse;\r
- long lRequest;\r
- unsigned char gap[nNoMansLandSize];\r
- /* followed by:\r
- * unsigned char data[nDataSize];\r
- * unsigned char anotherGap[nNoMansLandSize];\r
- */\r
-} _CrtMemBlockHeader;\r
-\r
-/*\r
-int MyAllocHook(int nAllocType, void *pvData,\r
- size_t nSize, int nBlockUse, long lRequest,\r
- const unsigned char * szFileName, int nLine)\r
-{\r
- if ( nBlockUse == _CRT_BLOCK )\r
- return( TRUE );\r
- if (nAllocType == _HOOK_FREE) {\r
- _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);\r
- if (ptr->nDataSize == 8192)\r
- fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize);\r
- }\r
- else if (nAllocType == _HOOK_ALLOC && nSize == 8192)\r
- fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);\r
- return (TRUE);\r
-}\r
-*/\r
-\r
-int real_main(int preinit)\r
-{\r
- SPConfig& conf=SPConfig::getConfig();\r
- if (preinit) {\r
-\r
- // Initialize the SP library.\r
- conf.setFeatures(\r
- SPConfig::Listener |\r
- SPConfig::Caching |\r
- SPConfig::Metadata |\r
- SPConfig::Trust |\r
- SPConfig::Credentials |\r
- SPConfig::AttributeResolution |\r
- SPConfig::Handlers |\r
- SPConfig::OutOfProcess |\r
- (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)\r
- );\r
- if (!shar_config)\r
- shar_config=getenv("SHIBSP_CONFIG");\r
- if (!shar_schemadir)\r
- shar_schemadir=getenv("SHIBSP_SCHEMAS");\r
- if (!shar_schemadir)\r
- shar_schemadir=SHIBSP_SCHEMAS;\r
- if (!shar_config)\r
- shar_config=SHIBSP_CONFIG;\r
- if (!conf.init(shar_schemadir)) {\r
- fprintf(stderr, "configuration is invalid, see console for specific problems\n");\r
- return -1;\r
- }\r
- \r
- try {\r
- static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h);\r
- static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
- xercesc::DOMDocument* dummydoc=XMLToolingConfig::getConfig().getParser().newDocument();\r
- XercesJanitor<xercesc::DOMDocument> docjanitor(dummydoc);\r
- xercesc::DOMElement* dummy = dummydoc->createElementNS(NULL,path);\r
- auto_ptr_XMLCh src(shar_config);\r
- dummy->setAttributeNS(NULL,path,src.get());\r
- dummy->setAttributeNS(NULL,validate,xmlconstants::XML_ONE);\r
- \r
- conf.setServiceProvider(conf.ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER,dummy));\r
- conf.getServiceProvider()->init();\r
- }\r
- catch (exception& ex) {\r
- fprintf(stderr, "caught exception while loading configuration: %s\n", ex.what());\r
- conf.term();\r
- return -2;\r
- }\r
-\r
- // If just a test run, bail.\r
- if (shar_checkonly) {\r
- fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");\r
- return 0;\r
- }\r
- }\r
- else {\r
-\r
- //_CrtSetAllocHook(MyAllocHook);\r
-\r
- // Run the listener\r
- if (!shar_checkonly) {\r
-\r
- // Run the listener.\r
- if (!conf.getServiceProvider()->getListenerService()->run(&shibd_shutdown)) {\r
- fprintf(stderr, "listener failed to enter listen loop\n");\r
- return -3;\r
- }\r
- }\r
-\r
- conf.term();\r
- }\r
- return 0;\r
-}\r
-\r
-#else\r
-\r
-static void term_handler(int arg)\r
-{\r
- shibd_shutdown = true;\r
-}\r
-\r
-static int setup_signals(void)\r
-{\r
- struct sigaction sa;\r
- memset(&sa, 0, sizeof (sa));\r
- sa.sa_handler = SIG_IGN;\r
- sa.sa_flags = SA_RESTART;\r
-\r
- if (sigaction(SIGPIPE, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
-\r
- memset(&sa, 0, sizeof (sa));\r
- sa.sa_handler = term_handler;\r
- sa.sa_flags = SA_RESTART;\r
-\r
- if (sigaction(SIGHUP, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
- if (sigaction(SIGINT, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
- if (sigaction(SIGQUIT, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
- if (sigaction(SIGTERM, &sa, NULL) < 0) {\r
- return -1;\r
- }\r
- return 0;\r
-}\r
-\r
-static void usage(char* whoami)\r
-{\r
- fprintf(stderr, "usage: %s [-fcdt]\n", whoami);\r
- fprintf(stderr, " -c\tconfig file to use.\n");\r
- fprintf(stderr, " -x\tXML schema catalogs to use.\n");\r
- fprintf(stderr, " -t\tcheck configuration file for problems.\n");\r
- fprintf(stderr, " -f\tforce removal of listener socket.\n");\r
- fprintf(stderr, " -p\tpid file to use.\n");\r
- fprintf(stderr, " -h\tprint this help message.\n");\r
- exit(1);\r
-}\r
-\r
-static int parse_args(int argc, char* argv[])\r
-{\r
- int opt;\r
-\r
- while ((opt = getopt(argc, argv, "c:x:p:fth")) > 0) {\r
- switch (opt) {\r
- case 'c':\r
- shar_config=optarg;\r
- break;\r
- case 'x':\r
- shar_schemadir=optarg;\r
- break;\r
- case 'f':\r
- unlink_socket = 1;\r
- break;\r
- case 't':\r
- shar_checkonly=true;\r
- break;\r
- case 'p':\r
- pidfile=optarg;\r
- break;\r
- default:\r
- return -1;\r
- }\r
- }\r
- return 0;\r
-}\r
-\r
-int main(int argc, char *argv[])\r
-{\r
- if (setup_signals() != 0)\r
- return -1;\r
-\r
- if (parse_args(argc, argv) != 0)\r
- usage(argv[0]);\r
-\r
- if (!shar_config)\r
- shar_config=getenv("SHIBSP_CONFIG");\r
- if (!shar_schemadir)\r
- shar_schemadir=getenv("SHIBSP_SCHEMAS");\r
- if (!shar_schemadir)\r
- shar_schemadir=SHIBSP_SCHEMAS;\r
- if (!shar_config)\r
- shar_config=SHIBSP_CONFIG;\r
-\r
- // initialize the shib-target library\r
- SPConfig& conf=SPConfig::getConfig();\r
- conf.setFeatures(\r
- SPConfig::Listener |\r
- SPConfig::Caching |\r
- SPConfig::Metadata |\r
- SPConfig::Trust |\r
- SPConfig::Credentials |\r
- SPConfig::AttributeResolution |\r
- SPConfig::Handlers |\r
- SPConfig::OutOfProcess |\r
- (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)\r
- );\r
- if (!conf.init(shar_schemadir)) {\r
- fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
- return -1;\r
- }\r
-\r
- try {\r
- static const XMLCh path[] = UNICODE_LITERAL_4(p,a,t,h);\r
- static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
- xercesc::DOMDocument* dummydoc=XMLToolingConfig::getConfig().getParser().newDocument();\r
- XercesJanitor<xercesc::DOMDocument> docjanitor(dummydoc);\r
- xercesc::DOMElement* dummy = dummydoc->createElementNS(NULL,path);\r
- auto_ptr_XMLCh src(shar_config);\r
- dummy->setAttributeNS(NULL,path,src.get());\r
- dummy->setAttributeNS(NULL,validate,xmlconstants::XML_ONE);\r
-\r
- conf.setServiceProvider(conf.ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER,dummy));\r
- conf.getServiceProvider()->init();\r
- }\r
- catch (exception& ex) {\r
- fprintf(stderr, "caught exception while loading configuration: %s\n", ex.what());\r
- conf.term();\r
- return -2;\r
- }\r
-\r
- if (shar_checkonly)\r
- fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");\r
- else {\r
-\r
- // Write the pid file\r
- if (pidfile) {\r
- FILE* pidf = fopen(pidfile, "w");\r
- if (pidf) {\r
- fprintf(pidf, "%d\n", getpid());\r
- fclose(pidf);\r
- } else {\r
- perror(pidfile); // keep running though\r
- }\r
- }\r
- \r
- // Run the listener\r
- if (!conf.getServiceProvider()->getListenerService()->run(&shibd_shutdown)) {\r
- fprintf(stderr, "listener failed to enter listen loop\n");\r
- return -3;\r
- }\r
- }\r
-\r
- conf.term();\r
- if (pidfile)\r
- unlink(pidfile);\r
- return 0;\r
-}\r
-\r
-#endif\r
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the
+ * License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
+ */
+
+/*
+ * shibd.cpp -- the shibd "main" code.
+ */
+
+
+// eventually we might be able to support autoconf via cygwin...
+#if defined (_MSC_VER) || defined(__BORLANDC__)
+# include "config_win32.h"
+#else
+# include "config.h"
+#endif
+
+#ifdef WIN32
+# define _CRT_NONSTDC_NO_DEPRECATE 1
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <shibsp/SPConfig.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# include <sys/select.h>
+#endif
+
+#if defined(HAVE_GRP_H) && defined(HAVE_PWD_H)
+# include <pwd.h>
+# include <grp.h>
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+#include <shibsp/ServiceProvider.h>
+#include <shibsp/remoting/ListenerService.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+
+#ifdef HAVE_SD_NOTIFY
+#include <systemd/sd-daemon.h>
+#else
+#define SD_EMERG ""
+#define SD_ALERT ""
+#define SD_CRIT ""
+#define SD_ERR ""
+#define SD_WARNING ""
+#define SD_NOTICE ""
+#define SD_INFO ""
+#define SD_DEBUG ""
+#endif
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+bool shibd_shutdown = false;
+const char* shar_config = nullptr;
+const char* shar_schemadir = nullptr;
+const char* shar_prefix = nullptr;
+bool shar_checkonly = false;
+bool shar_version = false;
+static bool unlink_socket = false;
+const char* pidfile = nullptr;
+
+#ifdef WIN32
+
+//#include <CRTDBG.H>
+
+#define nNoMansLandSize 4
+typedef struct _CrtMemBlockHeader
+{
+ struct _CrtMemBlockHeader * pBlockHeaderNext;
+ struct _CrtMemBlockHeader * pBlockHeaderPrev;
+ char * szFileName;
+ int nLine;
+ size_t nDataSize;
+ int nBlockUse;
+ long lRequest;
+ unsigned char gap[nNoMansLandSize];
+ /* followed by:
+ * unsigned char data[nDataSize];
+ * unsigned char anotherGap[nNoMansLandSize];
+ */
+} _CrtMemBlockHeader;
+
+/*
+int MyAllocHook(int nAllocType, void *pvData,
+ size_t nSize, int nBlockUse, long lRequest,
+ const unsigned char * szFileName, int nLine)
+{
+ if ( nBlockUse == _CRT_BLOCK )
+ return( TRUE );
+ if (nAllocType == _HOOK_FREE) {
+ _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);
+ if (ptr->nDataSize == 8192)
+ fprintf(stderr,"free request %u size %u\n", ptr->lRequest, ptr->nDataSize);
+ }
+ else if (nAllocType == _HOOK_ALLOC && nSize == 8192)
+ fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);
+ return (TRUE);
+}
+*/
+
+int real_main(int preinit)
+{
+ if (shar_version) {
+ if (preinit)
+ fprintf(stdout, PACKAGE_STRING"\n");
+ return 0;
+ }
+
+ SPConfig& conf = SPConfig::getConfig();
+ if (preinit) {
+ // Initialize the SP library.
+ conf.setFeatures(
+ SPConfig::Listener |
+ SPConfig::Caching |
+ SPConfig::Metadata |
+ SPConfig::Trust |
+ SPConfig::Credentials |
+ SPConfig::AttributeResolution |
+ SPConfig::Handlers |
+ SPConfig::OutOfProcess |
+ (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
+ );
+ if (!conf.init(shar_schemadir, shar_prefix)) {
+ fprintf(stderr, "configuration is invalid, see console for specific problems\n");
+ return -1;
+ }
+
+ if (!conf.instantiate(shar_config)) {
+ fprintf(stderr, "configuration is invalid, check console for specific problems\n");
+ conf.term();
+ return -2;
+ }
+
+ // If just a test run, bail.
+ if (shar_checkonly) {
+ fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
+ return 0;
+ }
+ }
+ else {
+
+ //_CrtSetAllocHook(MyAllocHook);
+
+ if (!shar_checkonly) {
+ // Run the listener.
+ ListenerService* listener = conf.getServiceProvider()->getListenerService();
+ if (!listener->init(unlink_socket)) {
+ fprintf(stderr, "listener failed to initialize\n");
+ conf.term();
+ return -3;
+ }
+ else if (!listener->run(&shibd_shutdown)) {
+ fprintf(stderr, "listener failed during service\n");
+ listener->term();
+ conf.term();
+ return -3;
+ }
+ listener->term();
+ }
+
+ conf.term();
+ }
+ return 0;
+}
+
+#else
+
+int daemon_wait = 3;
+bool shibd_running = false;
+bool daemonize = true;
+const char* runasuser = nullptr;
+const char* runasgroup = nullptr;
+
+static void term_handler(int arg)
+{
+ shibd_shutdown = true;
+}
+
+static void run_handler(int arg)
+{
+ shibd_running = true;
+}
+
+static void child_handler(int arg)
+{
+ // Terminate the parent's wait/sleep if the newly born daemon dies early.
+}
+
+static int setup_signals(void)
+{
+ struct sigaction sa;
+ memset(&sa, 0, sizeof (sa));
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_RESTART;
+
+ if (sigaction(SIGPIPE, &sa, nullptr) < 0) {
+ return -1;
+ }
+
+ memset(&sa, 0, sizeof (sa));
+ sa.sa_handler = term_handler;
+ sa.sa_flags = SA_RESTART;
+
+ if (sigaction(SIGHUP, &sa, nullptr) < 0) {
+ return -1;
+ }
+ if (sigaction(SIGINT, &sa, nullptr) < 0) {
+ return -1;
+ }
+ if (sigaction(SIGQUIT, &sa, nullptr) < 0) {
+ return -1;
+ }
+ if (sigaction(SIGTERM, &sa, nullptr) < 0) {
+ return -1;
+ }
+
+ if (daemonize) {
+ memset(&sa, 0, sizeof (sa));
+ sa.sa_handler = run_handler;
+
+ if (sigaction(SIGUSR1, &sa, nullptr) < 0) {
+ return -1;
+ }
+
+ memset(&sa, 0, sizeof (sa));
+ sa.sa_handler = child_handler;
+
+ if (sigaction(SIGCHLD, &sa, nullptr) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void usage(char* whoami)
+{
+ fprintf(stderr, "usage: %s [-dcxtfFpwugvh]\n", whoami);
+ fprintf(stderr, " -d\tinstallation prefix to use\n");
+ fprintf(stderr, " -c\tconfig file to use\n");
+ fprintf(stderr, " -x\tXML schema catalogs to use\n");
+ fprintf(stderr, " -t\ttest configuration file for problems\n");
+ fprintf(stderr, " -f\tforce removal of listener socket\n");
+ fprintf(stderr, " -F\tstay in the foreground\n");
+ fprintf(stderr, " -p\tpid file to use\n");
+ fprintf(stderr, " -w\tseconds to wait for successful daemonization\n");
+ fprintf(stderr, " -u\tuser to run under\n");
+ fprintf(stderr, " -g\tgroup to run under\n");
+ fprintf(stderr, " -v\tprint software version\n");
+ fprintf(stderr, " -h\tprint this help message\n");
+ exit(1);
+}
+
+static int parse_args(int argc, char* argv[])
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "d:c:x:p:w:u:g:fFtvh")) > 0) {
+ switch (opt) {
+ case 'd':
+ shar_prefix=optarg;
+ break;
+ case 'c':
+ shar_config=optarg;
+ break;
+ case 'x':
+ shar_schemadir=optarg;
+ break;
+ case 'f':
+ unlink_socket = true;
+ break;
+ case 'F':
+ daemonize = false;
+ break;
+ case 't':
+ shar_checkonly=true;
+ daemonize=false;
+ break;
+ case 'v':
+ shar_version=true;
+ break;
+ case 'p':
+ pidfile=optarg;
+ break;
+ case 'w':
+ if (optarg)
+ daemon_wait = atoi(optarg);
+ if (daemon_wait <= 0)
+ daemon_wait = 3;
+ break;
+ case 'u':
+ if (optarg)
+ runasuser = optarg;
+ break;
+ case 'g':
+ if (optarg)
+ runasgroup = optarg;
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ if (parse_args(argc, argv) != 0)
+ usage(argv[0]);
+ else if (shar_version) {
+ fprintf(stdout, PACKAGE_STRING"\n");
+ return 0;
+ }
+
+ if (setup_signals() != 0)
+ return -1;
+
+ if (runasgroup) {
+#ifdef HAVE_GETGRNAM
+ struct group* grp = getgrnam(runasgroup);
+ if (!grp) {
+ fprintf(stderr, "getgrnam failed, check -g option\n");
+ return -1;
+ }
+ if (setgid(grp->gr_gid) != 0) {
+ fprintf(stderr, "setgid failed, check -g option\n");
+ return -1;
+ }
+#else
+ fprintf(stderr, "-g not supported on this platform");
+ return -1;
+#endif
+ }
+
+ if (runasuser) {
+#ifdef HAVE_GETPWNAM
+ struct passwd* pwd = getpwnam(runasuser);
+ if (!pwd) {
+ fprintf(stderr, "getpwnam failed, check -u option\n");
+ return -1;
+ }
+#ifdef HAVE_INITGROUPS
+ // w/out initgroups/setgroups process retains supplementary groups
+ if (initgroups(pwd->pw_name, pwd->pw_gid) != 0) {
+ fprintf(stderr, "initgroups failed, check -u option\n");
+ return -1;
+ }
+#endif
+ if (setuid(pwd->pw_uid) != 0) {
+ fprintf(stderr, "setuid failed, check -u option\n");
+ return -1;
+ }
+#else
+ fprintf(stderr, "-u not supported on this platform");
+ return -1;
+#endif
+ }
+
+ // initialize the shib-target library
+ SPConfig& conf=SPConfig::getConfig();
+ conf.setFeatures(
+ SPConfig::Listener |
+ SPConfig::Caching |
+ SPConfig::Metadata |
+ SPConfig::Trust |
+ SPConfig::Credentials |
+ SPConfig::AttributeResolution |
+ SPConfig::Handlers |
+ SPConfig::OutOfProcess |
+ (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
+ );
+ if (!conf.init(shar_schemadir, shar_prefix)) {
+ fprintf(stderr, SD_ERR "configuration is invalid, check console for specific problems\n");
+ return -1;
+ }
+
+ if (daemonize) {
+ // We must fork() early, while we're single threaded.
+ // StorageService cleanup thread is about to start.
+ switch (fork()) {
+ case 0:
+ break;
+ case -1:
+ perror("forking");
+ exit(EXIT_FAILURE);
+ default:
+ sleep(daemon_wait);
+ exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);
+ }
+ }
+
+ if (!conf.instantiate(shar_config)) {
+ fprintf(stderr, SD_ERR "configuration is invalid, check console for specific problems\n");
+ conf.term();
+ return -2;
+ }
+
+ if (shar_checkonly)
+ fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
+ else {
+ // Init the listener.
+ ListenerService* listener = conf.getServiceProvider()->getListenerService();
+ if (!listener->init(unlink_socket)) {
+ fprintf(stderr, SD_ERR "listener failed to initialize\n");
+ conf.term();
+ return -3;
+ }
+
+ if (daemonize) {
+ if (setsid() == -1) {
+ perror("setsid");
+ exit(EXIT_FAILURE);
+ }
+ if (chdir("/") == -1) {
+ perror("chdir to root");
+ exit(EXIT_FAILURE);
+ }
+
+ if (pidfile) {
+ FILE* pidf = fopen(pidfile, "w");
+ if (pidf) {
+ fprintf(pidf, "%d\n", getpid());
+ fclose(pidf);
+ }
+ else {
+ perror(pidfile);
+ }
+ }
+
+ freopen("/dev/null", "r", stdin);
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+
+ // Signal our parent that we are A-OK.
+ kill(getppid(), SIGUSR1);
+ }
+
+ // Run the listener.
+#ifdef HAVE_SD_NOTIFY
+ sd_notify(0, "READY=1");
+#endif
+ if (!listener->run(&shibd_shutdown)) {
+ fprintf(stderr, SD_ERR "listener failure during service\n");
+ listener->term();
+ conf.term();
+ if (daemonize && pidfile)
+ unlink(pidfile);
+ return -3;
+ }
+ listener->term();
+ }
+#ifdef HAVE_SD_NOTIFY
+ sd_notify(0, "STOPPING=1");
+#endif
+ conf.term();
+ if (daemonize && pidfile)
+ unlink(pidfile);
+ return 0;
+}
+
+#endif