Starting migration to new SP library
[shibboleth/cpp-sp.git] / shar / shar.cpp
1 /*
2  *  Copyright 2001-2005 Internet2
3  * 
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /*
18  * shar.cpp -- the shibd "main" code.  All the functionality is elsewhere
19  *
20  * Created By:  Derek Atkins <derek@ihtfp.com>
21  *
22  * $Id$
23  */
24
25
26 // eventually we might be able to support autoconf via cygwin...
27 #if defined (_MSC_VER) || defined(__BORLANDC__)
28 # include "config_win32.h"
29 #else
30 # include "config.h"
31 #endif
32
33 #ifdef WIN32
34 # define _CRT_NONSTDC_NO_DEPRECATE 1
35 # define _CRT_SECURE_NO_DEPRECATE 1
36 #endif
37
38 #include <shib-target/shib-target.h>
39 #include <shibsp/SPConfig.h>
40
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #include <sys/select.h>
44 #endif
45
46 #include <stdio.h>
47 #include <signal.h>
48 #include <log4cpp/Category.hh>
49
50 using namespace shibsp;
51 using namespace shibtarget;
52 using namespace shibboleth;
53 using namespace saml;
54 using namespace log4cpp;
55 using namespace std;
56
57 bool shibd_shutdown = false;
58 const char* shar_config = NULL;
59 const char* shar_schemadir = NULL;
60 bool shar_checkonly = false;
61 static int unlink_socket = 0;
62 const char* pidfile = NULL;
63
64 #ifdef WIN32
65
66 //#include <CRTDBG.H>
67
68 #define nNoMansLandSize 4
69 typedef struct _CrtMemBlockHeader
70 {
71         struct _CrtMemBlockHeader * pBlockHeaderNext;
72         struct _CrtMemBlockHeader * pBlockHeaderPrev;
73         char *                      szFileName;
74         int                         nLine;
75         size_t                      nDataSize;
76         int                         nBlockUse;
77         long                        lRequest;
78         unsigned char               gap[nNoMansLandSize];
79         /* followed by:
80          *  unsigned char           data[nDataSize];
81          *  unsigned char           anotherGap[nNoMansLandSize];
82          */
83 } _CrtMemBlockHeader;
84
85 /*
86 int MyAllocHook(int nAllocType, void *pvData,
87       size_t nSize, int nBlockUse, long lRequest,
88       const unsigned char * szFileName, int nLine)
89 {
90     if ( nBlockUse == _CRT_BLOCK )
91       return( TRUE );
92     if (nAllocType == _HOOK_FREE) {
93         _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);
94         if (ptr->nDataSize == 8192)
95             fprintf(stderr,"free  request %u size %u\n", ptr->lRequest, ptr->nDataSize);
96     }
97     else if (nAllocType == _HOOK_ALLOC && nSize == 8192)
98         fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);
99     return (TRUE);
100 }
101 */
102
103 int real_main(int preinit)
104 {
105     ShibTargetConfig& conf=ShibTargetConfig::getConfig();
106     if (preinit) {
107
108         // initialize the shib-target library
109         SPConfig::getConfig().setFeatures(
110             SPConfig::Listener |
111             SPConfig::Caching |
112             SPConfig::Metadata |
113             SPConfig::Trust |
114             SPConfig::Credentials |
115             SPConfig::AAP |
116             SPConfig::OutOfProcess |
117             (shar_checkonly ? (SPConfig::InProcess | SPConfig::RequestMapper) : SPConfig::Logging)
118             );
119         if (!shar_config)
120             shar_config=getenv("SHIBCONFIG");
121         if (!shar_schemadir)
122             shar_schemadir=getenv("SHIBSCHEMAS");
123         if (!shar_schemadir)
124             shar_schemadir=SHIB_SCHEMAS;
125         if (!shar_config)
126             shar_config=SHIB_CONFIG;
127         if (!conf.init(shar_schemadir) || !conf.load(shar_config)) {
128             fprintf(stderr, "configuration is invalid, see console for specific problems\n");
129             return -2;
130         }
131
132         // If just a test run, bail.
133         if (shar_checkonly) {
134             fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");
135             return 0;
136         }
137     }
138     else {
139
140         //_CrtSetAllocHook(MyAllocHook);
141
142         // Run the listener
143         if (!shar_checkonly) {
144
145             // Run the listener.
146             if (!conf.getINI()->getListener()->run(&shibd_shutdown)) {
147                 fprintf(stderr, "listener failed to enter listen loop\n");
148                 return -3;
149             }
150         }
151
152         conf.shutdown();
153     }
154     return 0;
155 }
156
157 #else
158
159 static void term_handler(int arg)
160 {
161     shibd_shutdown = true;
162 }
163
164 static int setup_signals(void)
165 {
166     struct sigaction sa;
167     memset(&sa, 0, sizeof (sa));
168     sa.sa_handler = SIG_IGN;
169     sa.sa_flags = SA_RESTART;
170
171     if (sigaction(SIGPIPE, &sa, NULL) < 0) {
172         return -1;
173     }
174
175     memset(&sa, 0, sizeof (sa));
176     sa.sa_handler = term_handler;
177     sa.sa_flags = SA_RESTART;
178
179     if (sigaction(SIGHUP, &sa, NULL) < 0) {
180         return -1;
181     }
182     if (sigaction(SIGINT, &sa, NULL) < 0) {
183         return -1;
184     }
185     if (sigaction(SIGQUIT, &sa, NULL) < 0) {
186         return -1;
187     }
188     if (sigaction(SIGTERM, &sa, NULL) < 0) {
189         return -1;
190     }
191     return 0;
192 }
193
194 static void usage(char* whoami)
195 {
196     fprintf(stderr, "usage: %s [-fcdt]\n", whoami);
197     fprintf(stderr, "  -c\tconfig file to use.\n");
198     fprintf(stderr, "  -d\tschema directory to use.\n");
199     fprintf(stderr, "  -t\tcheck configuration file for problems.\n");
200     fprintf(stderr, "  -f\tforce removal of listener socket.\n");
201     fprintf(stderr, "  -p\tpid file to use.\n");
202     fprintf(stderr, "  -h\tprint this help message.\n");
203     exit(1);
204 }
205
206 static int parse_args(int argc, char* argv[])
207 {
208     int opt;
209
210     while ((opt = getopt(argc, argv, "c:d:p:fth")) > 0) {
211         switch (opt) {
212             case 'c':
213                 shar_config=optarg;
214                 break;
215             case 'd':
216                 shar_schemadir=optarg;
217                 break;
218             case 'f':
219                 unlink_socket = 1;
220                 break;
221             case 't':
222                 shar_checkonly=true;
223                 break;
224             case 'p':
225                 pidfile=optarg;
226                 break;
227             default:
228                 return -1;
229         }
230     }
231     return 0;
232 }
233
234 int main(int argc, char *argv[])
235 {
236     if (setup_signals() != 0)
237         return -1;
238
239     if (parse_args(argc, argv) != 0)
240         usage(argv[0]);
241
242     if (!shar_config)
243         shar_config=getenv("SHIBCONFIG");
244     if (!shar_schemadir)
245         shar_schemadir=getenv("SHIBSCHEMAS");
246     if (!shar_schemadir)
247         shar_schemadir=SHIB_SCHEMAS;
248     if (!shar_config)
249         shar_config=SHIB_CONFIG;
250
251     // initialize the shib-target library
252     ShibTargetConfig& conf=ShibTargetConfig::getConfig();
253     SPConfig::getConfig().setFeatures(
254         SPConfig::Listener |
255         SPConfig::Caching |
256         SPConfig::Metadata |
257         SPConfig::Trust |
258         SPConfig::Credentials |
259         SPConfig::AAP |
260         SPConfig::OutOfProcess |
261         (shar_checkonly ? (SPConfig::InProcess | SPConfig::RequestMapper) : SPConfig::Logging)
262         );
263     if (!conf.init(shar_schemadir) || !conf.load(shar_config)) {
264         fprintf(stderr, "configuration is invalid, check console for specific problems\n");
265         return -2;
266     }
267
268     if (shar_checkonly)
269         fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
270     else {
271
272         // Write the pid file
273         if (pidfile) {
274             FILE* pidf = fopen(pidfile, "w");
275             if (pidf) {
276                 fprintf(pidf, "%d\n", getpid());
277                 fclose(pidf);
278             } else {
279                 perror(pidfile);  // keep running though
280             }
281         }
282     
283         // Run the listener
284         if (!conf.getINI()->getListener()->run(&shibd_shutdown)) {
285             fprintf(stderr, "listener failed to enter listen loop\n");
286             return -3;
287         }
288     }
289
290     conf.shutdown();
291     if (pidfile)
292         unlink(pidfile);
293     return 0;
294 }
295
296 #endif