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