Use AM_LDFLAGS instead of LDFLAGS
[yazpp-moved-to-github.git] / src / yaz-proxy-main.cpp
1 /*
2  * Copyright (c) 1998-2004, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Id: yaz-proxy-main.cpp,v 1.30 2004-01-12 22:35:26 adam Exp $
6  */
7
8 #include <signal.h>
9 #include <unistd.h>
10 #include <pwd.h>
11 #include <sys/types.h>
12
13 #include <yaz/log.h>
14 #include <yaz/options.h>
15
16 #include <yaz++/socket-manager.h>
17 #include <yaz++/pdu-assoc.h>
18 #include <yaz++/proxy.h>
19
20 void usage(char *prog)
21 {
22     fprintf (stderr, "%s: [-c config] [-l log] [-a log] [-v level] [-t target] "
23              "[-u uid] [-p pidfile] @:port\n", prog);
24     exit (1);
25 }
26
27 static char *pid_fname = 0;
28 static char *uid = 0;
29 static char *log_file = 0;
30 static int debug = 0;
31
32 int args(Yaz_Proxy *proxy, int argc, char **argv)
33 {
34     char *addr = 0;
35     char *arg;
36     char *prog = argv[0];
37     int ret;
38
39     while ((ret = options("o:a:t:v:c:u:i:m:l:T:p:U:X",
40                           argv, argc, &arg)) != -2)
41     {
42         int err;
43         switch (ret)
44         {
45         case 0:
46             if (addr)
47             {
48                 usage(prog);
49                 return 1;
50             }
51             addr = arg;
52             break;
53         case 'c':
54             err = proxy->set_config(arg);
55             if (err == -2)
56             {
57                 fprintf(stderr, "Config file support not enabled (proxy not compiled with libxml2 support)\n");
58                 exit(1);
59             }
60             else if (err == -1)
61             {
62                 fprintf(stderr, "Bad or missing file %s\n", arg);
63                 exit(1);
64             }
65             break;
66         case 'a':
67             proxy->set_APDU_log(arg);
68             break;
69         case 't':
70             proxy->set_default_target(arg);
71             break;
72         case 'U':
73             proxy->set_proxy_authentication(arg);
74             break;
75         case 'o':
76             proxy->option("optimize", arg);
77             break;
78         case 'v':
79             yaz_log_init_level (yaz_log_mask_str(arg));
80             break;
81         case 'l':
82             yaz_log_init_file (arg);
83             log_file = xstrdup(arg);
84             break;
85         case 'm':
86             proxy->set_max_clients(atoi(arg));
87             break;
88         case 'i':
89             proxy->set_client_idletime(atoi(arg));
90             break;
91         case 'T':
92             proxy->set_target_idletime(atoi(arg));
93             break;
94         case 'X':
95             debug = 1;
96             break;
97         case 'p':
98             if (!pid_fname)
99                 pid_fname = xstrdup(arg);
100             break;
101         case 'u':
102             if (!uid)
103                 uid = xstrdup(arg);
104             break;
105         default:
106             usage(prog);
107             return 1;
108         }
109     }
110     if (addr)
111     {
112         if (proxy->server(addr))
113         {
114             yaz_log(LOG_FATAL|LOG_ERRNO, "listen %s", addr);
115             exit(1);
116         }
117     }
118     else
119     {
120         usage(prog);
121         return 1;
122     }
123     return 0;
124 }
125
126 static Yaz_Proxy *static_yaz_proxy = 0;
127 static void sighup_handler(int num)
128 {
129     signal(SIGHUP, sighup_handler);
130     if (static_yaz_proxy)
131         static_yaz_proxy->reconfig();
132 }
133
134
135 static void child_run(Yaz_SocketManager *m, int run)
136 {
137     signal(SIGHUP, sighup_handler);
138
139     yaz_log(LOG_LOG, "0 proxy run=%d pid=%ld", run, (long) getpid());
140     if (pid_fname)
141     {
142         FILE *f = fopen(pid_fname, "w");
143         if (!f)
144         {
145             yaz_log(LOG_ERRNO|LOG_FATAL, "Couldn't create %s", pid_fname);
146             exit(0);
147         }
148         fprintf(f, "%ld", (long) getpid());
149         fclose(f);
150         xfree(pid_fname);
151     }
152     if (uid)
153     {
154         struct passwd *pw;
155
156         if (!(pw = getpwnam(uid)))
157         {
158             yaz_log(LOG_FATAL, "%s: Unknown user", uid);
159             exit(3);
160         }
161         if (log_file)
162         {
163             chown(log_file, pw->pw_uid,  pw->pw_gid);
164             xfree(log_file);
165         }
166
167         if (setuid(pw->pw_uid) < 0)
168         {
169             yaz_log(LOG_FATAL|LOG_ERRNO, "setuid");
170             exit(4);
171         }
172         xfree(uid);
173     }
174
175     while (m->processEvent() > 0)
176         ;
177
178     exit (0);
179 }
180
181 int main(int argc, char **argv)
182 {
183 #if HAVE_XSLT
184     xmlInitMemory();
185     
186     LIBXML_TEST_VERSION
187 #endif
188     int cont = 1;
189     int run = 1;
190     Yaz_SocketManager mySocketManager;
191     Yaz_Proxy proxy(new Yaz_PDU_Assoc(&mySocketManager));
192
193     static_yaz_proxy = &proxy;
194
195     args(&proxy, argc, argv);
196
197     if (debug)
198     {
199         child_run(&mySocketManager, run);
200         exit(0);
201     }
202     while (cont)
203     {
204         pid_t p = fork();
205         if (p == (pid_t) -1)
206         {
207             yaz_log(LOG_FATAL|LOG_ERRNO, "fork");
208             exit(1);
209         }
210         else if (p == 0)
211         {
212             child_run(&mySocketManager, run);
213         }
214         pid_t p1;
215         int status;
216         p1 = wait(&status);
217
218         yaz_log_reopen();
219
220         if (p1 != p)
221         {
222             yaz_log(LOG_FATAL, "p1=%d != p=%d", p1, p);
223             exit(1);
224         }
225         if (WIFSIGNALED(status))
226         {
227             switch(WTERMSIG(status)) {
228             case SIGILL:
229                 yaz_log(LOG_WARN, "Received SIGILL from child %ld", (long) p);
230                 cont = 1;
231                 break;
232             case SIGABRT:
233                 yaz_log(LOG_WARN, "Received SIGABRT from child %ld", (long) p);
234                 cont = 1;
235                 break ;
236             case SIGSEGV:
237                 yaz_log(LOG_WARN, "Received SIGSEGV from child %ld", (long) p);
238                 cont = 1;
239                 break;
240             case SIGTERM:
241                 yaz_log(LOG_LOG, "Received SIGTERM from child %ld",
242                         (long) p);
243                 cont = 0;
244                 break;
245             default:
246                 yaz_log(LOG_WARN, "Received SIG %d from child %ld",
247                         WTERMSIG(status), (long) p);
248                 cont = 0;
249             }
250         }
251         else if (status == 0)
252             cont = 0;
253         else
254         {
255             yaz_log(LOG_LOG, "Exit %d from child %ld", status, (long) p);
256             cont = 1;
257         }
258         if (cont)
259             sleep(1);
260         run++;
261     }
262     exit (0);
263     return 0;
264 }