Same buildconf.sh as YAZ
[yazproxy-moved-to-github.git] / src / yaz-proxy-main.cpp
1 /* This file is part of YAZ proxy
2    Copyright (C) 1998-2008 Index Data
3
4 YAZ proxy 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 YAZ proxy 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 #include <signal.h>
20 #if HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #if HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif
26 #if HAVE_SYS_TIME_H
27 #include <sys/time.h>
28 #endif
29 #if HAVE_SYS_RESOURCE_H
30 #include <sys/resource.h>
31 #endif
32
33 #include <stdarg.h>
34 #include <stdlib.h>
35
36 #include <yaz/log.h>
37 #include <yaz/options.h>
38 #include <yaz/daemon.h>
39
40 #include <yazpp/socket-manager.h>
41 #include <yazpp/pdu-assoc.h>
42 #include <yazproxy/proxy.h>
43
44 #if YAZ_HAVE_XSLT
45 #include <libxml/parser.h>
46 #include <libxml/tree.h>
47 #include <libxslt/xsltutils.h>
48 #include <libxslt/transform.h>
49 #endif
50
51 #if YAZ_HAVE_EXSLT
52 #include <libexslt/exslt.h>
53 #endif
54
55 using namespace yazpp_1;
56
57 void usage(char *prog)
58 {
59     fprintf (stderr, "%s: [-a log] [-c config] [-D]\n"
60              " [-i sec] [-l log] [-m num] [-n num] [-p pidfile]"
61              " [-t target] [-T sec] [-u uid]\n"
62              " [-v level] [-X] [-V] @:port\n", prog);
63     exit (1);
64 }
65
66 static char *pid_fname = 0;
67 static char *uid = 0;
68 static char *log_file = 0;
69 static unsigned int daemon_flags = YAZ_DAEMON_KEEPALIVE;
70 static int no_limit_files = 0;
71
72 int args(Yaz_Proxy *proxy, int argc, char **argv)
73 {
74     char *addr = 0;
75     char *arg;
76     char *prog = argv[0];
77     int ret;
78
79     while ((ret = options("o:a:Dt:v:c:u:i:m:l:T:p:n:VX",
80                           argv, argc, &arg)) != -2)
81     {
82         int err;
83         switch (ret)
84         {
85         case 0:
86             if (addr)
87             {
88                 usage(prog);
89                 return 1;
90             }
91             addr = arg;
92             break;
93         case 'a':
94             proxy->set_APDU_log(arg);
95             break;
96         case 'c':
97             err = proxy->set_config(arg);
98             if (err == -2)
99             {
100                 fprintf(stderr, "Config file support not enabled (not using libxslt & libxml2)\n");
101                 exit(1);
102             }
103             else if (err == -1)
104             {
105                 fprintf(stderr, "Bad or missing file %s\n", arg);
106                 exit(1);
107             }
108             break;
109         case 'D':
110             daemon_flags |= YAZ_DAEMON_FORK;
111             break;
112         case 'i':
113             proxy->set_client_idletime(atoi(arg));
114             break;
115         case 'l':
116             yaz_log_init_file (arg);
117             log_file = xstrdup(arg);
118             break;
119         case 'm':
120             proxy->set_max_clients(atoi(arg));
121             break;
122         case 'n':
123             no_limit_files = atoi(arg);
124             break;
125         case 'o':
126             proxy->option("optimize", arg);
127             break;
128         case 'p':
129             if (!pid_fname)
130                 pid_fname = xstrdup(arg);
131             break;
132         case 't':
133             proxy->set_default_target(arg);
134             break;
135         case 'T':
136             proxy->set_target_idletime(atoi(arg));
137             break;
138         case 'u':
139             if (!uid)
140                 uid = xstrdup(arg);
141             break;
142         case 'v':
143             yaz_log_init_level (yaz_log_mask_str(arg));
144             break;
145         case 'V':
146             puts(
147 #ifdef VERSION
148                 VERSION
149 #else
150                 "unknown"
151 #endif
152                 );
153             exit(0);
154         case 'X':
155             proxy->set_debug_mode(1);
156             daemon_flags = YAZ_DAEMON_DEBUG;
157             break;
158         default:
159             usage(prog);
160             return 1;
161         }
162     }
163     if (addr)
164     {
165         if (proxy->server(addr))
166         {
167             yaz_log(YLOG_FATAL|YLOG_ERRNO, "listen %s", addr);
168             exit(1);
169         }
170     }
171     else
172     {
173         usage(prog);
174         return 1;
175     }
176     return 0;
177 }
178
179 static Yaz_Proxy *static_yaz_proxy = 0;
180 static void sighup_handler(int num)
181 {
182 #if WIN32
183 #else
184     signal(SIGHUP, sighup_handler);
185 #endif
186     if (static_yaz_proxy)
187         static_yaz_proxy->reconfig();
188 }
189
190 #if YAZ_HAVE_XSLT
191 static void proxy_xml_error_handler(void *ctx, const char *fmt, ...)
192 {
193     char buf[1024];
194
195     va_list ap;
196     va_start(ap, fmt);
197
198 #ifdef WIN32
199     vsprintf(buf, fmt, ap);
200 #else
201     vsnprintf(buf, sizeof(buf), fmt, ap);
202 #endif
203     yaz_log(YLOG_WARN, "%s: %s", (char*) ctx, buf);
204
205     va_end (ap);
206 }
207 #endif
208
209 static void child_run(void *data)
210 {
211     SocketManager *m = (SocketManager *) data;
212 #ifdef WIN32
213 #else
214     signal(SIGHUP, sighup_handler);
215 #endif
216
217 #if YAZ_HAVE_XSLT
218     xmlSetGenericErrorFunc((void *) "XML", proxy_xml_error_handler);
219     xsltSetGenericErrorFunc((void *) "XSLT", proxy_xml_error_handler);
220 #endif
221
222 #if YAZ_HAVE_EXSLT
223     exsltRegisterAll();
224 #endif
225 #ifdef WIN32
226 #else
227     yaz_log(YLOG_LOG, "0 proxy pid=%ld", (long) getpid());
228 #endif
229     if (no_limit_files)
230     {
231 #if HAVE_SETRLIMIT
232         struct rlimit limit_data;
233         limit_data.rlim_cur = no_limit_files;
234         limit_data.rlim_max = no_limit_files;
235         
236         yaz_log(YLOG_LOG, "0 setrlimit NOFILE cur=%ld max=%ld",
237                 (long) limit_data.rlim_cur, (long) limit_data.rlim_max);
238         if (setrlimit(RLIMIT_NOFILE, &limit_data))
239             yaz_log(YLOG_ERRNO|YLOG_WARN, "setrlimit");
240 #else
241         yaz_log(YLOG_WARN, "setrlimit unavablable. Option -n ignored");
242 #endif
243     }
244 #if HAVE_GETRLIMIT
245     struct rlimit limit_data;
246     getrlimit(RLIMIT_NOFILE, &limit_data);
247     yaz_log(YLOG_LOG, "0 getrlimit NOFILE cur=%ld max=%ld",
248             (long) limit_data.rlim_cur, (long) limit_data.rlim_max);
249 #endif
250     
251     while (m->processEvent() > 0)
252         ;
253
254     exit (0);
255 }
256
257 int main(int argc, char **argv)
258 {
259 #if YAZ_HAVE_XSLT
260     xmlInitMemory();
261     
262     LIBXML_TEST_VERSION
263 #endif
264     SocketManager mySocketManager;
265     Yaz_Proxy proxy(new PDU_Assoc(&mySocketManager), &mySocketManager);
266
267     static_yaz_proxy = &proxy;
268
269     args(&proxy, argc, argv);
270
271     yaz_daemon("yazproxy", daemon_flags,
272                child_run, &mySocketManager, pid_fname, uid);
273     exit (0);
274     return 0;
275 }
276 /*
277  * Local variables:
278  * c-basic-offset: 4
279  * indent-tabs-mode: nil
280  * End:
281  * vim: shiftwidth=4 tabstop=8 expandtab
282  */
283