chdir may be defined in unistd.h
[pazpar2-moved-to-github.git] / src / pazpar2.c
1 /* This file is part of Pazpar2.
2    Copyright (C) 2006-2011 Index Data
3
4 Pazpar2 is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Pazpar2 is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #ifdef WIN32
24 #include <winsock.h>
25 #endif
26 #if HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29
30 #include <signal.h>
31 #include <assert.h>
32
33 #include "parameters.h"
34 #include "session.h"
35 #include "ppmutex.h"
36 #include <yaz/daemon.h>
37 #include <yaz/log.h>
38 #include <yaz/options.h>
39 #include <yaz/sc.h>
40
41 // #define MTRACE
42 #ifdef MTRACE
43 #include <mcheck.h>
44 #endif
45
46 static struct conf_config *sc_stop_config = 0;
47
48 void child_handler(void *data)
49 {
50     struct conf_config *config = (struct conf_config *) data;
51
52     config_process_events(config);
53
54     config_destroy(config);
55 }
56
57 static void show_version(void)
58 {
59     char yaz_version_str[80];
60     printf("Pazpar2 " PACKAGE_VERSION 
61 #ifdef PAZPAR2_VERSION_SHA1
62            " "
63            PAZPAR2_VERSION_SHA1
64 #endif
65 "\n");
66
67     yaz_version(yaz_version_str, 0);
68
69     printf("Configuration:");
70 #if YAZ_HAVE_ICU
71     printf(" icu:enabled");
72 #else
73     printf(" icu:disabled");
74 #endif
75     printf(" yaz:%s", yaz_version_str);
76     printf("\n");
77     exit(0);
78 }            
79
80 #ifdef WIN32
81 static int tcpip_init (void)
82 {
83     WORD requested;
84     WSADATA wd;
85
86     requested = MAKEWORD(1, 1);
87     if (WSAStartup(requested, &wd))
88         return 0;
89     return 1;
90 }
91 #endif
92
93
94 static int sc_main(
95     yaz_sc_t s, 
96     int argc, char **argv)
97 {
98     int daemon = 0;
99     int ret;
100     int log_file_in_use = 0;
101     char *arg;
102     const char *pidfile = 0;
103     const char *uid = 0;
104     const char *listener_override = 0;
105     const char *config_fname = 0;
106     const char *record_fname = 0;
107     struct conf_config *config = 0;
108     int test_mode = 0;
109
110 #ifndef WIN32
111     if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
112         yaz_log(YLOG_WARN|YLOG_ERRNO, "signal");
113 #else
114     tcpip_init();
115 #endif
116
117     yaz_log_init_prefix("pazpar2");
118     yaz_log_xml_errors(0, YLOG_WARN);
119
120     while ((ret = options("dDf:h:l:p:R:tu:v:VX", argv, argc, &arg)) != -2)
121     {
122         switch (ret)
123         {
124         case 'd':
125             global_parameters.dump_records = 1;
126             break;
127         case 'D':
128             daemon = 1;
129             break;
130         case 'f':
131             config_fname = arg;
132             break;
133         case 'h':
134             listener_override = arg;
135             break;
136         case 'l':
137             yaz_log_init_file(arg);
138             log_file_in_use = 1;
139             break;
140         case 'p':
141             pidfile = arg;
142             break;
143         case 'R':
144             record_fname = arg;
145             global_parameters.predictable_sessions = 1;
146             break;
147         case 't':
148             test_mode = 1;
149             break;
150         case 'u':
151             uid = arg;
152             break;
153         case 'v':
154             yaz_log_init_level(yaz_log_mask_str(arg));
155             break;
156         case 'V':
157             show_version();
158             break;
159         case 'w':
160             if (chdir(arg))
161             {
162                 yaz_log(YLOG_FATAL|YLOG_ERRNO, "chdir %s", arg);
163                 return 1;
164             }
165             break;
166         case 'X':
167             global_parameters.debug_mode++;
168             global_parameters.predictable_sessions = 1;
169             break;
170         default:
171             fprintf(stderr, "Usage: pazpar2\n"
172                     "    -d                      Show internal records\n"
173                     "    -D                      Daemon mode (background)\n"
174                     "    -f configfile           Configuration\n"
175                     "    -h [host:]port          Listener port\n"
176                     "    -l file                 Log to file\n"
177                     "    -p pidfile              PID file\n"
178                     "    -R recfile              HTTP recording file\n"
179                     "    -t                      Test configuration\n"
180                     "    -u uid                  Change user to uid\n"
181                     "    -V                      Show version\n"
182                     "    -v level                Set log level\n"
183                     "    -w dir                  Working directory\n"
184                     "    -X                      Debug mode\n"
185 #ifdef WIN32
186                     "    -install                Install windows service\n"
187                     "    -remove                 Remove windows service\n"
188 #endif
189                 );
190             return 1;
191         }
192     }
193     if (!config_fname)
194     {
195         yaz_log(YLOG_FATAL, "Configuration must be given with option -f");
196         return 1;
197     }
198     pazpar2_mutex_init();
199     
200     config = config_create(config_fname, global_parameters.dump_records);
201     if (!config)
202         return 1;
203     sc_stop_config = config;
204     if (test_mode)
205     {
206         yaz_log(YLOG_LOG, "Configuration OK");
207         config_destroy(config);
208     }
209     else
210     {
211         yaz_log(YLOG_LOG, "Pazpar2 " VERSION  " "
212 #ifdef PAZPAR2_VERSION_SHA1
213                 PAZPAR2_VERSION_SHA1
214 #else
215                 "-"
216 #endif
217                 " started");
218         if (daemon && !log_file_in_use)
219         {
220             yaz_log(YLOG_FATAL, "Logfile must be given (option -l) for daemon "
221                     "mode");
222             return 1;
223         }
224         ret = config_start_listeners(config, listener_override, record_fname);
225         if (ret)
226             return ret; /* error starting http listener */
227         
228         yaz_sc_running(s);
229         
230         yaz_daemon("pazpar2",
231                    (global_parameters.debug_mode ? YAZ_DAEMON_DEBUG : 0) +
232                    (daemon ? YAZ_DAEMON_FORK : 0) + YAZ_DAEMON_KEEPALIVE,
233                    child_handler, config /* child_data */,
234                    pidfile, uid);
235     }
236     return 0;
237 }
238
239
240 static void sc_stop(yaz_sc_t s)
241 {
242     config_stop_listeners(sc_stop_config);
243 }
244
245 int main(int argc, char **argv)
246 {
247     int ret;
248     yaz_sc_t s = yaz_sc_create("pazpar2", "Pazpar2");
249     
250 #ifdef MTRACE
251     mtrace();
252 #endif
253
254     ret = yaz_sc_program(s, argc, argv, sc_main, sc_stop);
255
256     yaz_sc_destroy(&s);
257
258 #ifdef MTRACE
259     muntrace();
260 #endif
261
262
263     exit(ret);
264 }
265
266 /*
267  * Local variables:
268  * c-basic-offset: 4
269  * c-file-style: "Stroustrup"
270  * indent-tabs-mode: nil
271  * End:
272  * vim: shiftwidth=4 tabstop=8 expandtab
273  */
274