Updated copyright headers. Omit CVS IDs.
[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] @: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:X",
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 'X':
146             proxy->set_debug_mode(1);
147             daemon_flags = YAZ_DAEMON_DEBUG;
148             break;
149         default:
150             usage(prog);
151             return 1;
152         }
153     }
154     if (addr)
155     {
156         if (proxy->server(addr))
157         {
158             yaz_log(YLOG_FATAL|YLOG_ERRNO, "listen %s", addr);
159             exit(1);
160         }
161     }
162     else
163     {
164         usage(prog);
165         return 1;
166     }
167     return 0;
168 }
169
170 static Yaz_Proxy *static_yaz_proxy = 0;
171 static void sighup_handler(int num)
172 {
173 #if WIN32
174 #else
175     signal(SIGHUP, sighup_handler);
176 #endif
177     if (static_yaz_proxy)
178         static_yaz_proxy->reconfig();
179 }
180
181 #if YAZ_HAVE_XSLT
182 static void proxy_xml_error_handler(void *ctx, const char *fmt, ...)
183 {
184     char buf[1024];
185
186     va_list ap;
187     va_start(ap, fmt);
188
189 #ifdef WIN32
190     vsprintf(buf, fmt, ap);
191 #else
192     vsnprintf(buf, sizeof(buf), fmt, ap);
193 #endif
194     yaz_log(YLOG_WARN, "%s: %s", (char*) ctx, buf);
195
196     va_end (ap);
197 }
198 #endif
199
200 static void child_run(void *data)
201 {
202     SocketManager *m = (SocketManager *) data;
203 #ifdef WIN32
204 #else
205     signal(SIGHUP, sighup_handler);
206 #endif
207
208 #if YAZ_HAVE_XSLT
209     xmlSetGenericErrorFunc((void *) "XML", proxy_xml_error_handler);
210     xsltSetGenericErrorFunc((void *) "XSLT", proxy_xml_error_handler);
211 #endif
212
213 #if YAZ_HAVE_EXSLT
214     exsltRegisterAll();
215 #endif
216 #ifdef WIN32
217 #else
218     yaz_log(YLOG_LOG, "0 proxy pid=%ld", (long) getpid());
219 #endif
220     if (no_limit_files)
221     {
222 #if HAVE_SETRLIMIT
223         struct rlimit limit_data;
224         limit_data.rlim_cur = no_limit_files;
225         limit_data.rlim_max = no_limit_files;
226         
227         yaz_log(YLOG_LOG, "0 setrlimit NOFILE cur=%ld max=%ld",
228                 (long) limit_data.rlim_cur, (long) limit_data.rlim_max);
229         if (setrlimit(RLIMIT_NOFILE, &limit_data))
230             yaz_log(YLOG_ERRNO|YLOG_WARN, "setrlimit");
231 #else
232         yaz_log(YLOG_WARN, "setrlimit unavablable. Option -n ignored");
233 #endif
234     }
235 #if HAVE_GETRLIMIT
236     struct rlimit limit_data;
237     getrlimit(RLIMIT_NOFILE, &limit_data);
238     yaz_log(YLOG_LOG, "0 getrlimit NOFILE cur=%ld max=%ld",
239             (long) limit_data.rlim_cur, (long) limit_data.rlim_max);
240 #endif
241     
242     while (m->processEvent() > 0)
243         ;
244
245     exit (0);
246 }
247
248 int main(int argc, char **argv)
249 {
250 #if YAZ_HAVE_XSLT
251     xmlInitMemory();
252     
253     LIBXML_TEST_VERSION
254 #endif
255     SocketManager mySocketManager;
256     Yaz_Proxy proxy(new PDU_Assoc(&mySocketManager), &mySocketManager);
257
258     static_yaz_proxy = &proxy;
259
260     args(&proxy, argc, argv);
261
262     yaz_daemon("yazproxy", daemon_flags,
263                child_run, &mySocketManager, pid_fname, uid);
264     exit (0);
265     return 0;
266 }
267 /*
268  * Local variables:
269  * c-basic-offset: 4
270  * indent-tabs-mode: nil
271  * End:
272  * vim: shiftwidth=4 tabstop=8 expandtab
273  */
274